feat: add notifications and display sections in forms example

This commit is contained in:
Ahmed 2023-09-11 17:01:14 +01:00
parent abc5f5f2bc
commit 5a2174de7a
10 changed files with 315 additions and 8 deletions

View File

@ -0,0 +1,5 @@
<script setup>
import DisplayExample from "@/examples/forms/Display.vue"
</script>
<DisplayExample />

View File

@ -0,0 +1,5 @@
<script setup>
import NotificationsExample from "@/examples/forms/Notifications.vue"
</script>
<NotificationsExample />

View File

@ -0,0 +1,10 @@
<script setup lang="ts">
import FormsLayout from './layouts/FormsLayout.vue'
import DisplayForm from './components/DisplayForm.vue'
</script>
<template>
<FormsLayout>
<DisplayForm />
</FormsLayout>
</template>

View File

@ -0,0 +1,10 @@
<script setup lang="ts">
import FormsLayout from './layouts/FormsLayout.vue'
import NotificationsForm from './components/NotificationsForm.vue'
</script>
<template>
<FormsLayout>
<NotificationsForm />
</FormsLayout>
</template>

View File

@ -17,7 +17,7 @@ import {
import { Button } from '@/lib/registry/new-york/ui/button'
const appearenceForm = ref({
theme: '',
theme: 'light',
font: '',
})

View File

@ -0,0 +1,100 @@
<script setup lang="ts">
import { ref } from 'vue'
import * as z from 'zod'
import { cn } from '@/lib/utils'
import { Label } from '@/lib/registry/new-york/ui/label'
import { Separator } from '@/lib/registry/new-york/ui/separator'
import { Checkbox } from '@/lib/registry/new-york/ui/checkbox'
import { Button } from '@/lib/registry/new-york/ui/button'
const displayForm = ref({
items: ['recents', 'home'],
})
const items = [
{
id: 'recents',
label: 'Recents',
checked: true,
},
{
id: 'home',
label: 'Home',
checked: true,
},
{
id: 'applications',
label: 'Applications',
checked: false,
},
{
id: 'desktop',
label: 'Desktop',
checked: false,
},
{
id: 'downloads',
label: 'Downloads',
checked: false,
},
{
id: 'documents',
label: 'Documents',
checked: false,
},
] as const
const displayFormSchema = z.object({
items: z.array(z.string()).refine(value => value.some(item => item), {
message: 'You have to select at least one item.',
}),
})
type DisplayFormValues = z.infer<typeof displayFormSchema>
const errors = ref<z.ZodFormattedError<DisplayFormValues> | null>(null)
async function handleSubmit() {
const result = displayFormSchema.safeParse(displayForm.value)
if (!result.success) {
errors.value = result.error.format()
console.log(errors.value)
return
}
console.log('Form submitted!', displayForm.value)
}
</script>
<template>
<div>
<h3 class="text-lg font-medium">
Display
</h3>
<p class="text-sm text-muted-foreground">
Turn items on or off to control what's displayed in the app.
</p>
</div>
<Separator />
<form @submit.prevent="handleSubmit">
<div class="mb-4">
<Label for="sidebar" :class="cn('text-md', errors?.items && 'text-destructive')">
Sidebar
</Label>
<span class="text-xs text-muted-foreground">
Select the items you want to display in the sidebar.
</span>
</div>
<div v-for="item in items" :key="item.id" class="pb-1">
<div class="flex flex-row items-center space-x-3 space-y-0">
<Checkbox :id="item.id" v-model:checked="item.checked" :value="item.id" />
<Label :for="item.id">{{ item.label }}</Label>
</div>
</div>
<div class="flex justify-start mt-4">
<Button type="submit">
Update display
</Button>
</div>
</form>
</template>

View File

@ -0,0 +1,176 @@
<script setup lang="ts">
import { ref } from 'vue'
import * as z from 'zod'
import { cn } from '@/lib/utils'
import { Label } from '@/lib/registry/new-york/ui/label'
import { Separator } from '@/lib/registry/new-york/ui/separator'
import { RadioGroup, RadioGroupItem } from '@/lib/registry/new-york/ui/radio-group'
import { Switch } from '@/lib/registry/new-york/ui/switch'
import { Checkbox } from '@/lib/registry/new-york/ui/checkbox'
import { Button } from '@/lib/registry/new-york/ui/button'
const notificationsForm = ref({
type: '',
mobile: false,
communication_emails: false,
social_emails: true,
marketing_emails: false,
security_emails: true,
})
const notificationsFormSchema = z.object({
type: z.enum(['all', 'mentions', 'none'], {
required_error: 'You need to select a notification type.',
}),
mobile: z.boolean().default(false).optional(),
communication_emails: z.boolean().default(false).optional(),
social_emails: z.boolean().default(false).optional(),
marketing_emails: z.boolean().default(false).optional(),
security_emails: z.boolean(),
})
type notificationsFormValues = z.infer<typeof notificationsFormSchema>
const errors = ref<z.ZodFormattedError<notificationsFormValues> | null>(null)
async function handleSubmit() {
const result = notificationsFormSchema.safeParse(notificationsForm.value)
if (!result.success) {
errors.value = result.error.format()
console.log(errors.value)
return
}
console.log('Form submitted!', notificationsForm.value)
}
</script>
<template>
<div>
<h3 class="text-lg font-medium">
Notifications
</h3>
<p class="text-sm text-muted-foreground">
Configure how you receive notifications.
</p>
</div>
<Separator />
<form class="space-y-8" @submit.prevent="handleSubmit">
<div class="grid gap-2">
<Label for="font" :class="cn('text-sm', errors?.type && 'text-destructive')">
Notify me about...
</Label>
<RadioGroup
v-model="notificationsForm.type"
default-value="all"
class="flex flex-col space-y-1"
>
<div class="flex items-center space-x-3 space-y-0">
<RadioGroupItem id="all" value="all" />
<Label for="all">All new messages</Label>
</div>
<div class="flex items-center space-x-3 space-y-0">
<RadioGroupItem id="mentions" value="mentions" />
<Label for="mentions">Direct messages and mentions</Label>
</div>
<div class="flex items-center space-x-3 space-y-0">
<RadioGroupItem id="none" value="none" />
<Label for="none">Nothing</Label>
</div>
<div v-if="errors?.type" class="text-sm text-destructive">
<span v-for="error in errors.type._errors" :key="error">{{ error }}</span>
</div>
</RadioGroup>
</div>
<div class="grid gap-2">
<h3 class="mb-4 text-lg font-medium">
Email Notifications
</h3>
<div class="space-y-4">
<div class="flex flex-row items-center justify-between rounded-lg border p-4">
<div class="space-y-0.5">
<Label class="text-base" for="communication_emails">
Communication emails
</Label>
<span class="text-xs text-muted-foreground">
Receive emails about your account activity.
</span>
</div>
<Switch
id="communication_emails"
v-model:checked="notificationsForm.communication_emails"
/>
</div>
</div>
<div class="flex flex-row items-center justify-between rounded-lg border p-4">
<div class="space-y-0.5">
<Label class="text-base" for="marketing_emails">
Marketing emails
</Label>
<span class="text-xs text-muted-foreground">
Receive emails about new products, features, and more.
</span>
</div>
<Switch
id="marketing_emails"
v-model:checked="notificationsForm.marketing_emails"
/>
</div>
<div class="flex flex-row items-center justify-between rounded-lg border p-4">
<div class="space-y-0.5">
<Label class="text-base" for="social_emails">
Social emails
</Label>
<span class="text-xs text-muted-foreground">
Receive emails for friend requests, follows, and more.
</span>
</div>
<Switch
id="social_emails"
v-model:checked="notificationsForm.social_emails"
/>
</div>
<div class="flex flex-row items-center justify-between rounded-lg border p-4">
<div class="space-y-0.5">
<Label class="text-base" for="security_emails">
Security emails
</Label>
<span class="text-xs text-muted-foreground">
Receive emails about your account activity and security.
</span>
</div>
<Switch
id="security_emails"
v-model:checked="notificationsForm.security_emails"
disabled
/>
</div>
</div>
<div class="grid gap-2">
<div class="flex flex-row items-start space-x-3 space-y-0">
<Checkbox
id="mobile"
v-model:checked="notificationsForm.mobile"
/>
<div>
<Label for="mobile">
Use different settings for my mobile devices
</Label>
<span class="text-xs text-muted-foreground">
You can manage your mobile notifications in the {{ " " }}
<a href="/examples/forms">mobile settings</a> page.
</span>
</div>
</div>
</div>
<div class="flex justify-start">
<Button type="submit">
Update notifications
</Button>
</div>
</form>
</template>

View File

@ -1,5 +1,6 @@
<script setup lang="ts">
import SidebarNav from '../components/SidebarNav.vue'
import { Separator } from '@/lib/registry/new-york/ui/separator'
</script>
<template>

View File

@ -1,12 +1,16 @@
<script setup lang="ts">
import { RadioGroupRoot, type RadioGroupRootProps } from 'radix-vue'
import { cn } from '@/lib/utils'
import { RadioGroupRoot, type RadioGroupRootEmits, type RadioGroupRootProps } from 'radix-vue'
import { cn, useEmitAsProps } from '@/lib/utils'
const props = defineProps<RadioGroupRootProps & { class?: string }>()
const emits = defineEmits<RadioGroupRootEmits>()
const emitsAsProps = useEmitAsProps(emits)
</script>
<template>
<RadioGroupRoot :class="cn('grid gap-2', props.class)" v-bind="props">
<RadioGroupRoot :class="cn('grid gap-2', props.class)" v-bind="{ ...props, ...emitsAsProps }">
<slot />
</RadioGroupRoot>
</template>

View File

@ -5,10 +5,6 @@ export default {
darkMode: 'class',
content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx,md}', './.vitepress/**/*.{vue,js,ts,jsx,tsx}'],
theme: {
fontFamily: {
sans: ['Inter', 'sans-serif'],
mono: ['JetBrains Mono', 'monospace'],
},
container: {
center: true,
padding: '2rem',