docs: add form example for checkbox input and datepicker
This commit is contained in:
parent
854cb8f20c
commit
5868374679
|
|
@ -30,6 +30,16 @@ import { Checkbox } from '@/components/ui/checkbox'
|
|||
|
||||
## Examples
|
||||
|
||||
### With text
|
||||
|
||||
<ComponentPreview name="CheckboxWithText" />
|
||||
|
||||
### Disabled
|
||||
|
||||
<ComponentPreview name="CheckboxDisabled" />
|
||||
<ComponentPreview name="CheckboxDisabled" />
|
||||
|
||||
### Form
|
||||
|
||||
<ComponentPreview name="CheckboxFormSingle" />
|
||||
|
||||
<ComponentPreview name="CheckboxFormMultiple" />
|
||||
|
|
|
|||
|
|
@ -58,10 +58,12 @@ const date = ref<Date>()
|
|||
|
||||
### Date Range Picker
|
||||
|
||||
<ComponentPreview name="DatePickerWithRange" />
|
||||
|
||||
<ComponentPreview name="DatePickerWithRange" />
|
||||
|
||||
### Date Picker
|
||||
|
||||
<ComponentPreview name="DatePickerDemo" />
|
||||
|
||||
<ComponentPreview name="DatePickerDemo" />
|
||||
### Form
|
||||
|
||||
<ComponentPreview name="DatePickerForm" />
|
||||
|
|
|
|||
|
|
@ -50,13 +50,13 @@ The `<Form />` component is a wrapper around the `vee-validate` library. It prov
|
|||
</Form>
|
||||
```
|
||||
|
||||
## Examples
|
||||
## Example
|
||||
|
||||
|
||||
<TabPreview name="Component" :names="['Component', 'Native']">
|
||||
<template #Component>
|
||||
|
||||
#### Input Component
|
||||
#### `Input` Component
|
||||
|
||||
```vue
|
||||
<FormField v-slot="{ componentField }">
|
||||
|
|
@ -75,7 +75,7 @@ The `<Form />` component is a wrapper around the `vee-validate` library. It prov
|
|||
|
||||
<template #Native>
|
||||
|
||||
#### Native input element
|
||||
#### native `input` element
|
||||
|
||||
```vue
|
||||
<FormField v-slot="{ field }">
|
||||
|
|
@ -312,7 +312,20 @@ That's it. You now have a fully accessible form that is type-safe with client-si
|
|||
|
||||
<ComponentPreview
|
||||
name="InputForm"
|
||||
className="[&_[role=tablist]]:hidden [&>div>div:first-child]:hidden"
|
||||
class="[&_[role=tablist]]:hidden [&>div>div:first-child]:hidden"
|
||||
/>
|
||||
|
||||
</Steps>
|
||||
|
||||
## Examples
|
||||
|
||||
See the following links for more examples on how to use the `vee-validate` features with other components:
|
||||
|
||||
- [Checkbox](/docs/components/checkbox#form)
|
||||
- [Date Picker](/docs/components/date-picker#form)
|
||||
- [Input](/docs/components/input#form)
|
||||
- [Radio Group](/docs/components/radio-group#form)
|
||||
- [Select](/docs/components/select#form)
|
||||
- [Switch](/docs/components/switch#form)
|
||||
- [Textarea](/docs/components/textarea#form)
|
||||
- [Combobox](/docs/components/combobox#form)
|
||||
|
|
|
|||
|
|
@ -41,4 +41,28 @@ import { Input } from '@/components/ui/input'
|
|||
<template>
|
||||
<Input />
|
||||
</template>
|
||||
```
|
||||
```
|
||||
|
||||
### Default
|
||||
|
||||
<ComponentPreview name="InputDemo" class="[&_input]:max-w-xs" />
|
||||
|
||||
### File
|
||||
|
||||
<ComponentPreview name="InputFile" class="[&_input]:max-w-xs" />
|
||||
|
||||
### Disabled
|
||||
|
||||
<ComponentPreview name="InputDisabled" class="[&_input]:max-w-xs" />
|
||||
|
||||
### With Label
|
||||
|
||||
<ComponentPreview name="InputWithLabel" class="[&_input]:max-w-xs" />
|
||||
|
||||
### With Button
|
||||
|
||||
<ComponentPreview name="InputWithButton" class="[&_input]:max-w-xs" />
|
||||
|
||||
### Form
|
||||
|
||||
<ComponentPreview name="InputForm" />
|
||||
|
|
|
|||
|
|
@ -85,7 +85,9 @@ const onSubmit = handleSubmit((values) => {
|
|||
<Checkbox
|
||||
:checked="value.includes(item.id)"
|
||||
@update:checked="(checked) => {
|
||||
handleChange(checked ? [...value, item.id] : value.filter(id => id !== item.id))
|
||||
if (Array.isArray(value)) {
|
||||
handleChange(checked ? [...value, item.id] : value.filter(id => id !== item.id))
|
||||
}
|
||||
}"
|
||||
/>
|
||||
</FormControl>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { Checkbox } from '@/lib/registry/default/ui/checkbox'
|
|||
<div class="flex items-center space-x-2">
|
||||
<Checkbox id="terms" />
|
||||
<label
|
||||
htmlFor="terms"
|
||||
for="terms"
|
||||
class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
||||
>
|
||||
Accept terms and conditions
|
||||
|
|
|
|||
|
|
@ -0,0 +1,102 @@
|
|||
<script setup lang="ts">
|
||||
import { useForm } from 'vee-validate'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import * as z from 'zod'
|
||||
|
||||
import { Button } from '@/lib/registry/default/ui/button'
|
||||
import {
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@/lib/registry/default/ui/form'
|
||||
import { Checkbox } from '@/lib/registry/default/ui/checkbox'
|
||||
|
||||
const items = [
|
||||
{
|
||||
id: 'recents',
|
||||
label: 'Recents',
|
||||
},
|
||||
{
|
||||
id: 'home',
|
||||
label: 'Home',
|
||||
},
|
||||
{
|
||||
id: 'applications',
|
||||
label: 'Applications',
|
||||
},
|
||||
{
|
||||
id: 'desktop',
|
||||
label: 'Desktop',
|
||||
},
|
||||
{
|
||||
id: 'downloads',
|
||||
label: 'Downloads',
|
||||
},
|
||||
{
|
||||
id: 'documents',
|
||||
label: 'Documents',
|
||||
},
|
||||
] as const
|
||||
|
||||
const formSchema = toTypedSchema(z.object({
|
||||
items: z.array(z.string()).refine(value => value.some(item => item), {
|
||||
message: 'You have to select at least one item.',
|
||||
}),
|
||||
}))
|
||||
|
||||
const { handleSubmit } = useForm({
|
||||
validationSchema: formSchema,
|
||||
initialValues: {
|
||||
items: ['recents', 'home'],
|
||||
},
|
||||
})
|
||||
|
||||
const onSubmit = handleSubmit((values) => {
|
||||
console.log('Form submitted!', values)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form @submit="onSubmit">
|
||||
<FormField name="items">
|
||||
<FormItem>
|
||||
<div class="mb-4">
|
||||
<FormLabel class="text-base">
|
||||
Sidebar
|
||||
</FormLabel>
|
||||
<FormDescription>
|
||||
Select the items you want to display in the sidebar.
|
||||
</FormDescription>
|
||||
</div>
|
||||
|
||||
<FormField v-for="item in items" v-slot="{ value, handleChange }" :key="item.id" name="items">
|
||||
<FormItem :key="item.id" class="flex flex-row items-start space-x-3 space-y-0">
|
||||
<FormControl>
|
||||
<Checkbox
|
||||
:checked="value.includes(item.id)"
|
||||
@update:checked="(checked) => {
|
||||
if (Array.isArray(value)) {
|
||||
handleChange(checked ? [...value, item.id] : value.filter(id => id !== item.id))
|
||||
}
|
||||
}"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormLabel class="font-normal">
|
||||
{{ item.label }}
|
||||
</FormLabel>
|
||||
</FormItem>
|
||||
</FormField>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
|
||||
<div class="flex justify-start mt-4">
|
||||
<Button type="submit">
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
<script setup lang="ts">
|
||||
import { useForm } from 'vee-validate'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import * as z from 'zod'
|
||||
|
||||
import { Button } from '@/lib/registry/default/ui/button'
|
||||
import {
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@/lib/registry/default/ui/form'
|
||||
import { Checkbox } from '@/lib/registry/default/ui/checkbox'
|
||||
|
||||
const formSchema = toTypedSchema(z.object({
|
||||
mobile: z.boolean().default(false).optional(),
|
||||
}))
|
||||
|
||||
const { handleSubmit } = useForm({
|
||||
validationSchema: formSchema,
|
||||
initialValues: {
|
||||
mobile: true,
|
||||
},
|
||||
})
|
||||
|
||||
const onSubmit = handleSubmit((values) => {
|
||||
console.log('Form submitted!', values)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form class="space-y-6" @submit="onSubmit">
|
||||
<FormField v-slot="{ value, handleChange }" name="mobile">
|
||||
<FormItem class="flex flex-row items-start gap-x-3 space-y-0 rounded-md border p-4">
|
||||
<FormControl>
|
||||
<Checkbox :checked="value" @update:checked="handleChange" />
|
||||
</FormControl>
|
||||
<div class="space-y-1 leading-none">
|
||||
<FormLabel>Use different settings for my mobile devices</FormLabel>
|
||||
<FormDescription>
|
||||
You can manage your mobile notifications in the
|
||||
<a href="/examples/forms">mobile settings</a> page.
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</div>
|
||||
</FormItem>
|
||||
</FormField>
|
||||
<Button type="submit">
|
||||
Submit
|
||||
</Button>
|
||||
</Form>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<script setup lang="ts">
|
||||
import { Checkbox } from '@/lib/registry/default/ui/checkbox'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="items-top flex gap-x-2">
|
||||
<Checkbox id="terms1" />
|
||||
<div class="grid gap-1.5 leading-none">
|
||||
<label
|
||||
for="terms1"
|
||||
class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
||||
>
|
||||
Accept terms and conditions
|
||||
</label>
|
||||
<p class="text-sm text-muted-foreground">
|
||||
You agree to our Terms of Service and Privacy Policy.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
74
apps/www/src/lib/registry/default/example/DatePickerForm.vue
Normal file
74
apps/www/src/lib/registry/default/example/DatePickerForm.vue
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
<script setup lang="ts">
|
||||
import { format } from 'date-fns'
|
||||
import { Calendar as CalendarIcon } from 'lucide-vue-next'
|
||||
import { useForm } from 'vee-validate'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import * as z from 'zod'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
import { Button } from '@/lib/registry/default/ui/button'
|
||||
import { Calendar } from '@/lib/registry/default/ui/calendar'
|
||||
import {
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@/lib/registry/default/ui/form'
|
||||
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from '@/lib/registry/default/ui/popover'
|
||||
|
||||
const formSchema = toTypedSchema(z.object({
|
||||
dob: z.date({
|
||||
required_error: 'A date of birth is required.',
|
||||
}),
|
||||
}))
|
||||
|
||||
const { handleSubmit } = useForm({
|
||||
validationSchema: formSchema,
|
||||
})
|
||||
|
||||
const onSubmit = handleSubmit((values) => {
|
||||
console.log('Form submitted!', values)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form class="space-y-8" @submit="onSubmit">
|
||||
<FormField v-slot="{ componentField, value }" name="dob">
|
||||
<FormItem class="flex flex-col">
|
||||
<FormLabel>Date of birth</FormLabel>
|
||||
<Popover>
|
||||
<PopoverTrigger as-child>
|
||||
<FormControl>
|
||||
<Button
|
||||
variant="outline" :class="cn(
|
||||
'w-[240px] ps-3 text-start font-normal',
|
||||
!value && 'text-muted-foreground',
|
||||
)"
|
||||
>
|
||||
<span>{{ value ? format(value, "PPP") : "Pick a date" }}</span>
|
||||
<CalendarIcon class="ms-auto h-4 w-4 opacity-50" />
|
||||
</Button>
|
||||
</FormControl>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent class="p-0">
|
||||
<Calendar v-bind="componentField" />
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<FormDescription>
|
||||
Your date of birth is used to calculate your age.
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
<Button type="submit">
|
||||
Submit
|
||||
</Button>
|
||||
</Form>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import { Input } from '@/lib/registry/default/ui/input'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Input disabled type="email" placeholder="Email" />
|
||||
</template>
|
||||
11
apps/www/src/lib/registry/default/example/InputFile.vue
Normal file
11
apps/www/src/lib/registry/default/example/InputFile.vue
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<script setup lang="ts">
|
||||
import { Input } from '@/lib/registry/default/ui/input'
|
||||
import { Label } from '@/lib/registry/default/ui/label'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="grid w-full max-w-sm items-center gap-1.5">
|
||||
<Label for="picture">Picture</Label>
|
||||
<Input id="picture" type="file" />
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<script setup lang="ts">
|
||||
import { Input } from '@/lib/registry/default/ui/input'
|
||||
import { Button } from '@/lib/registry/default/ui/button'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex w-full max-w-sm items-center gap-1.5">
|
||||
<Input id="email" type="email" placeholder="Email" />
|
||||
<Button type="submit">
|
||||
Subscribe
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
11
apps/www/src/lib/registry/default/example/InputWithLabel.vue
Normal file
11
apps/www/src/lib/registry/default/example/InputWithLabel.vue
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<script setup lang="ts">
|
||||
import { Input } from '@/lib/registry/default/ui/input'
|
||||
import { Label } from '@/lib/registry/default/ui/label'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="grid w-full max-w-sm items-center gap-1.5">
|
||||
<Label for="email">Email</Label>
|
||||
<Input id="email" type="email" placeholder="Email" />
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -6,7 +6,7 @@ import { Checkbox } from '@/lib/registry/new-york/ui/checkbox'
|
|||
<div class="flex items-center space-x-2">
|
||||
<Checkbox id="terms" />
|
||||
<label
|
||||
htmlFor="terms"
|
||||
for="terms"
|
||||
class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
||||
>
|
||||
Accept terms and conditions
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
<script setup lang="ts">
|
||||
import { Checkbox } from '@/lib/registry/new-york/ui/checkbox'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="items-top flex space-x-2">
|
||||
<Checkbox id="terms1" disabled />
|
||||
<label
|
||||
for="terms2"
|
||||
class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
||||
>
|
||||
Accept terms and conditions
|
||||
</label>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
<script setup lang="ts">
|
||||
import { useForm } from 'vee-validate'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import * as z from 'zod'
|
||||
|
||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||
import {
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@/lib/registry/new-york/ui/form'
|
||||
import { Checkbox } from '@/lib/registry/new-york/ui/checkbox'
|
||||
|
||||
const items = [
|
||||
{
|
||||
id: 'recents',
|
||||
label: 'Recents',
|
||||
},
|
||||
{
|
||||
id: 'home',
|
||||
label: 'Home',
|
||||
},
|
||||
{
|
||||
id: 'applications',
|
||||
label: 'Applications',
|
||||
},
|
||||
{
|
||||
id: 'desktop',
|
||||
label: 'Desktop',
|
||||
},
|
||||
{
|
||||
id: 'downloads',
|
||||
label: 'Downloads',
|
||||
},
|
||||
{
|
||||
id: 'documents',
|
||||
label: 'Documents',
|
||||
},
|
||||
] as const
|
||||
|
||||
const formSchema = toTypedSchema(z.object({
|
||||
items: z.array(z.string()).refine(value => value.some(item => item), {
|
||||
message: 'You have to select at least one item.',
|
||||
}),
|
||||
}))
|
||||
|
||||
const { handleSubmit } = useForm({
|
||||
validationSchema: formSchema,
|
||||
initialValues: {
|
||||
items: ['recents', 'home'],
|
||||
},
|
||||
})
|
||||
|
||||
const onSubmit = handleSubmit((values) => {
|
||||
console.log('Form submitted!', values)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form @submit="onSubmit">
|
||||
<FormField name="items">
|
||||
<FormItem>
|
||||
<div class="mb-4">
|
||||
<FormLabel class="text-base">
|
||||
Sidebar
|
||||
</FormLabel>
|
||||
<FormDescription>
|
||||
Select the items you want to display in the sidebar.
|
||||
</FormDescription>
|
||||
</div>
|
||||
|
||||
<FormField v-for="item in items" v-slot="{ value, handleChange }" :key="item.id" name="items">
|
||||
<FormItem :key="item.id" class="flex flex-row items-start space-x-3 space-y-0">
|
||||
<FormControl>
|
||||
<Checkbox
|
||||
:checked="value.includes(item.id)"
|
||||
@update:checked="(checked) => {
|
||||
if (Array.isArray(value)) {
|
||||
handleChange(checked ? [...value, item.id] : value.filter(id => id !== item.id))
|
||||
}
|
||||
}"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormLabel class="font-normal">
|
||||
{{ item.label }}
|
||||
</FormLabel>
|
||||
</FormItem>
|
||||
</FormField>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
|
||||
<div class="flex justify-start mt-4">
|
||||
<Button type="submit">
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
<script setup lang="ts">
|
||||
import { useForm } from 'vee-validate'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import * as z from 'zod'
|
||||
|
||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||
import {
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@/lib/registry/new-york/ui/form'
|
||||
import { Checkbox } from '@/lib/registry/new-york/ui/checkbox'
|
||||
|
||||
const formSchema = toTypedSchema(z.object({
|
||||
mobile: z.boolean().default(false).optional(),
|
||||
}))
|
||||
|
||||
const { handleSubmit } = useForm({
|
||||
validationSchema: formSchema,
|
||||
initialValues: {
|
||||
mobile: true,
|
||||
},
|
||||
})
|
||||
|
||||
const onSubmit = handleSubmit((values) => {
|
||||
console.log('Form submitted!', values)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form class="space-y-6" @submit="onSubmit">
|
||||
<FormField v-slot="{ value, handleChange }" name="mobile">
|
||||
<FormItem class="flex flex-row items-start gap-x-3 space-y-0 rounded-md border p-4 shadow">
|
||||
<FormControl>
|
||||
<Checkbox :checked="value" @update:checked="handleChange" />
|
||||
</FormControl>
|
||||
<div class="space-y-1 leading-none">
|
||||
<FormLabel>Use different settings for my mobile devices</FormLabel>
|
||||
<FormDescription>
|
||||
You can manage your mobile notifications in the
|
||||
<a href="/examples/forms">mobile settings</a> page.
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</div>
|
||||
</FormItem>
|
||||
</FormField>
|
||||
<Button type="submit">
|
||||
Submit
|
||||
</Button>
|
||||
</Form>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<script setup lang="ts">
|
||||
import { Checkbox } from '@/lib/registry/new-york/ui/checkbox'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="items-top flex gap-x-2">
|
||||
<Checkbox id="terms1" />
|
||||
<div class="grid gap-1.5 leading-none">
|
||||
<label
|
||||
for="terms1"
|
||||
class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
||||
>
|
||||
Accept terms and conditions
|
||||
</label>
|
||||
<p class="text-sm text-muted-foreground">
|
||||
You agree to our Terms of Service and Privacy Policy.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -3,19 +3,19 @@ import { ref } from 'vue'
|
|||
import { CaretSortIcon, CheckIcon } from '@radix-icons/vue'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
import { Button } from '@/lib/registry/default/ui/button'
|
||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||
import {
|
||||
Command,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
} from '@/lib/registry/default/ui/command'
|
||||
} from '@/lib/registry/new-york/ui/command'
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from '@/lib/registry/default/ui/popover'
|
||||
} from '@/lib/registry/new-york/ui/popover'
|
||||
|
||||
const frameworks = [
|
||||
{ value: 'next.js', label: 'Next.js' },
|
||||
|
|
|
|||
|
|
@ -0,0 +1,74 @@
|
|||
<script setup lang="ts">
|
||||
import { format } from 'date-fns'
|
||||
import { CalendarIcon } from '@radix-icons/vue'
|
||||
import { useForm } from 'vee-validate'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import * as z from 'zod'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||
import { Calendar } from '@/lib/registry/new-york/ui/calendar'
|
||||
import {
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@/lib/registry/new-york/ui/form'
|
||||
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from '@/lib/registry/new-york/ui/popover'
|
||||
|
||||
const formSchema = toTypedSchema(z.object({
|
||||
dob: z.date({
|
||||
required_error: 'A date of birth is required.',
|
||||
}),
|
||||
}))
|
||||
|
||||
const { handleSubmit } = useForm({
|
||||
validationSchema: formSchema,
|
||||
})
|
||||
|
||||
const onSubmit = handleSubmit((values) => {
|
||||
console.log('Form submitted!', values)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form class="space-y-8" @submit="onSubmit">
|
||||
<FormField v-slot="{ componentField, value }" name="dob">
|
||||
<FormItem class="flex flex-col">
|
||||
<FormLabel>Date of birth</FormLabel>
|
||||
<Popover>
|
||||
<PopoverTrigger as-child>
|
||||
<FormControl>
|
||||
<Button
|
||||
variant="outline" :class="cn(
|
||||
'w-[240px] ps-3 text-start font-normal',
|
||||
!value && 'text-muted-foreground',
|
||||
)"
|
||||
>
|
||||
<span>{{ value ? format(value, "PPP") : "Pick a date" }}</span>
|
||||
<CalendarIcon class="ms-auto h-4 w-4 opacity-50" />
|
||||
</Button>
|
||||
</FormControl>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent class="p-0">
|
||||
<Calendar v-bind="componentField" />
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<FormDescription>
|
||||
Your date of birth is used to calculate your age.
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
<Button type="submit">
|
||||
Submit
|
||||
</Button>
|
||||
</Form>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import { Input } from '@/lib/registry/new-york/ui/input'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Input disabled type="email" placeholder="Email" />
|
||||
</template>
|
||||
11
apps/www/src/lib/registry/new-york/example/InputFile.vue
Normal file
11
apps/www/src/lib/registry/new-york/example/InputFile.vue
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<script setup lang="ts">
|
||||
import { Input } from '@/lib/registry/new-york/ui/input'
|
||||
import { Label } from '@/lib/registry/new-york/ui/label'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="grid w-full max-w-sm items-center gap-1.5">
|
||||
<Label for="picture">Picture</Label>
|
||||
<Input id="picture" type="file" />
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<script setup lang="ts">
|
||||
import { Input } from '@/lib/registry/new-york/ui/input'
|
||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex w-full max-w-sm items-center gap-1.5">
|
||||
<Input id="email" type="email" placeholder="Email" />
|
||||
<Button type="submit">
|
||||
Subscribe
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<script setup lang="ts">
|
||||
import { Input } from '@/lib/registry/new-york/ui/input'
|
||||
import { Label } from '@/lib/registry/new-york/ui/label'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="grid w-full max-w-sm items-center gap-1.5">
|
||||
<Label for="email">Email</Label>
|
||||
<Input id="email" type="email" placeholder="Email" />
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import { AlertDialogAction, type AlertDialogActionProps } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { buttonVariants } from '@/lib/registry/default/ui/button'
|
||||
import { buttonVariants } from '@/lib/registry/new-york/ui/button'
|
||||
|
||||
const props = defineProps<AlertDialogActionProps>()
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import { AlertDialogCancel, type AlertDialogCancelProps } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { buttonVariants } from '@/lib/registry/default/ui/button'
|
||||
import { buttonVariants } from '@/lib/registry/new-york/ui/button'
|
||||
|
||||
const props = defineProps<AlertDialogCancelProps>()
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user