feat: add notifications and display sections in forms example
This commit is contained in:
parent
abc5f5f2bc
commit
5a2174de7a
5
apps/www/src/content/examples/forms/display.md
Normal file
5
apps/www/src/content/examples/forms/display.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<script setup>
|
||||||
|
import DisplayExample from "@/examples/forms/Display.vue"
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DisplayExample />
|
||||||
5
apps/www/src/content/examples/forms/notifications.md
Normal file
5
apps/www/src/content/examples/forms/notifications.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<script setup>
|
||||||
|
import NotificationsExample from "@/examples/forms/Notifications.vue"
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<NotificationsExample />
|
||||||
10
apps/www/src/examples/forms/Display.vue
Normal file
10
apps/www/src/examples/forms/Display.vue
Normal 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>
|
||||||
10
apps/www/src/examples/forms/Notifications.vue
Normal file
10
apps/www/src/examples/forms/Notifications.vue
Normal 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>
|
||||||
|
|
@ -17,7 +17,7 @@ import {
|
||||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||||
|
|
||||||
const appearenceForm = ref({
|
const appearenceForm = ref({
|
||||||
theme: '',
|
theme: 'light',
|
||||||
font: '',
|
font: '',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
100
apps/www/src/examples/forms/components/DisplayForm.vue
Normal file
100
apps/www/src/examples/forms/components/DisplayForm.vue
Normal 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>
|
||||||
176
apps/www/src/examples/forms/components/NotificationsForm.vue
Normal file
176
apps/www/src/examples/forms/components/NotificationsForm.vue
Normal 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>
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import SidebarNav from '../components/SidebarNav.vue'
|
import SidebarNav from '../components/SidebarNav.vue'
|
||||||
|
import { Separator } from '@/lib/registry/new-york/ui/separator'
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,16 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { RadioGroupRoot, type RadioGroupRootProps } from 'radix-vue'
|
import { RadioGroupRoot, type RadioGroupRootEmits, type RadioGroupRootProps } from 'radix-vue'
|
||||||
import { cn } from '@/lib/utils'
|
import { cn, useEmitAsProps } from '@/lib/utils'
|
||||||
|
|
||||||
const props = defineProps<RadioGroupRootProps & { class?: string }>()
|
const props = defineProps<RadioGroupRootProps & { class?: string }>()
|
||||||
|
|
||||||
|
const emits = defineEmits<RadioGroupRootEmits>()
|
||||||
|
|
||||||
|
const emitsAsProps = useEmitAsProps(emits)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<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 />
|
<slot />
|
||||||
</RadioGroupRoot>
|
</RadioGroupRoot>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,6 @@ export default {
|
||||||
darkMode: 'class',
|
darkMode: 'class',
|
||||||
content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx,md}', './.vitepress/**/*.{vue,js,ts,jsx,tsx}'],
|
content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx,md}', './.vitepress/**/*.{vue,js,ts,jsx,tsx}'],
|
||||||
theme: {
|
theme: {
|
||||||
fontFamily: {
|
|
||||||
sans: ['Inter', 'sans-serif'],
|
|
||||||
mono: ['JetBrains Mono', 'monospace'],
|
|
||||||
},
|
|
||||||
container: {
|
container: {
|
||||||
center: true,
|
center: true,
|
||||||
padding: '2rem',
|
padding: '2rem',
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user