[{"data":1,"prerenderedAt":874},["ShallowReactive",2],{"navigation":3,"$fMW9jOOkNpZriWVK3P_bZYNOyYR2IEPvrHsC7cDBlJJc":404,"/docs/components/form":417,"surround-/docs/components/form":871},[4],{"title":5,"path":6,"stem":7,"children":8,"page":18},"Docs","/docs","docs",[9,273,299,317,330,356],{"title":10,"path":11,"stem":12,"children":13,"new":18,"type":272},"Components","/docs/components","docs/02.components",[14,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172,176,180,184,188,192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,252,256,260,264,268],{"title":15,"path":16,"stem":17,"new":18,"type":19,"children":-1},"Accordion","/docs/components/accordion","docs/components/accordion",false,"component",{"title":21,"path":22,"stem":23,"new":18,"type":19,"children":-1},"Alert","/docs/components/alert","docs/components/alert",{"title":25,"path":26,"stem":27,"new":18,"type":19,"children":-1},"Alert Dialog","/docs/components/alert-dialog","docs/components/alert-dialog",{"title":29,"path":30,"stem":31,"new":18,"type":19,"children":-1},"Aspect Ratio","/docs/components/aspect-ratio","docs/components/aspect-ratio",{"title":33,"path":34,"stem":35,"new":18,"type":19,"children":-1},"Avatar","/docs/components/avatar","docs/components/avatar",{"title":37,"path":38,"stem":39,"new":18,"type":19,"children":-1},"Badge","/docs/components/badge","docs/components/badge",{"title":41,"path":42,"stem":43,"new":18,"type":19,"children":-1},"Breadcrumb","/docs/components/breadcrumb","docs/components/breadcrumb",{"title":45,"path":46,"stem":47,"new":18,"type":19,"children":-1},"Button","/docs/components/button","docs/components/button",{"title":49,"path":50,"stem":51,"new":18,"type":19,"children":-1},"Button Group","/docs/components/button-group","docs/components/button-group",{"title":53,"path":54,"stem":55,"new":18,"type":19,"children":-1},"Calendar","/docs/components/calendar","docs/components/calendar",{"title":57,"path":58,"stem":59,"new":18,"type":19,"children":-1},"Card","/docs/components/card","docs/components/card",{"title":61,"path":62,"stem":63,"new":18,"type":19,"children":-1},"Carousel","/docs/components/carousel","docs/components/carousel",{"title":65,"path":66,"stem":67,"new":18,"type":19,"children":-1},"Chart","/docs/components/chart","docs/components/chart",{"title":69,"path":70,"stem":71,"new":18,"type":19,"children":-1},"Checkbox","/docs/components/checkbox","docs/components/checkbox",{"title":73,"path":74,"stem":75,"new":18,"type":19,"children":-1},"Collapsible","/docs/components/collapsible","docs/components/collapsible",{"title":77,"path":78,"stem":79,"new":18,"type":19,"children":-1},"Combobox","/docs/components/combobox","docs/components/combobox",{"title":81,"path":82,"stem":83,"new":18,"type":19,"children":-1},"Command","/docs/components/command","docs/components/command",{"title":85,"path":86,"stem":87,"new":18,"type":19,"children":-1},"Context Menu","/docs/components/context-menu","docs/components/context-menu",{"title":89,"path":90,"stem":91,"new":18,"type":19,"children":-1},"Data Table","/docs/components/data-table","docs/components/data-table",{"title":93,"path":94,"stem":95,"new":18,"type":19,"children":-1},"Date Picker","/docs/components/date-picker","docs/components/date-picker",{"title":97,"path":98,"stem":99,"new":18,"type":19,"children":-1},"Dialog","/docs/components/dialog","docs/components/dialog",{"title":101,"path":102,"stem":103,"new":18,"type":19,"children":-1},"Drawer","/docs/components/drawer","docs/components/drawer",{"title":105,"path":106,"stem":107,"new":18,"type":19,"children":-1},"Dropdown Menu","/docs/components/dropdown-menu","docs/components/dropdown-menu",{"title":109,"path":110,"stem":111,"new":18,"type":19,"children":-1},"Empty","/docs/components/empty","docs/components/empty",{"title":113,"path":114,"stem":115,"new":18,"type":19,"children":-1},"Field","/docs/components/field","docs/components/field",{"title":117,"path":118,"stem":119,"new":18,"type":19,"children":-1},"Form","/docs/components/form","docs/components/form",{"title":121,"path":122,"stem":123,"new":18,"type":19,"children":-1},"Hover Card","/docs/components/hover-card","docs/components/hover-card",{"title":125,"path":126,"stem":127,"new":18,"type":19,"children":-1},"Input","/docs/components/input","docs/components/input",{"title":129,"path":130,"stem":131,"new":18,"type":19,"children":-1},"Input Group","/docs/components/input-group","docs/components/input-group",{"title":133,"path":134,"stem":135,"new":18,"type":19,"children":-1},"Input OTP","/docs/components/input-otp","docs/components/input-otp",{"title":137,"path":138,"stem":139,"new":18,"type":19,"children":-1},"Item","/docs/components/item","docs/components/item",{"title":141,"path":142,"stem":143,"new":18,"type":19,"children":-1},"Kbd","/docs/components/kbd","docs/components/kbd",{"title":145,"path":146,"stem":147,"new":18,"type":19,"children":-1},"Label","/docs/components/label","docs/components/label",{"title":149,"path":150,"stem":151,"new":18,"type":19,"children":-1},"Menubar","/docs/components/menubar","docs/components/menubar",{"title":153,"path":154,"stem":155,"new":18,"type":19,"children":-1},"Native Select","/docs/components/native-select","docs/components/native-select",{"title":157,"path":158,"stem":159,"new":18,"type":19,"children":-1},"Navigation Menu","/docs/components/navigation-menu","docs/components/navigation-menu",{"title":161,"path":162,"stem":163,"new":18,"type":19,"children":-1},"Number Field","/docs/components/number-field","docs/components/number-field",{"title":165,"path":166,"stem":167,"new":18,"type":19,"children":-1},"Pagination","/docs/components/pagination","docs/components/pagination",{"title":169,"path":170,"stem":171,"new":18,"type":19,"children":-1},"Pin Input","/docs/components/pin-input","docs/components/pin-input",{"title":173,"path":174,"stem":175,"new":18,"type":19,"children":-1},"Popover","/docs/components/popover","docs/components/popover",{"title":177,"path":178,"stem":179,"new":18,"type":19,"children":-1},"Progress","/docs/components/progress","docs/components/progress",{"title":181,"path":182,"stem":183,"new":18,"type":19,"children":-1},"Radio Group","/docs/components/radio-group","docs/components/radio-group",{"title":185,"path":186,"stem":187,"new":18,"type":19,"children":-1},"Range Calendar","/docs/components/range-calendar","docs/components/range-calendar",{"title":189,"path":190,"stem":191,"new":18,"type":19,"children":-1},"Resizable","/docs/components/resizable","docs/components/resizable",{"title":193,"path":194,"stem":195,"new":18,"type":19,"children":-1},"Scroll Area","/docs/components/scroll-area","docs/components/scroll-area",{"title":197,"path":198,"stem":199,"new":18,"type":19,"children":-1},"Select","/docs/components/select","docs/components/select",{"title":201,"path":202,"stem":203,"new":18,"type":19,"children":-1},"Separator","/docs/components/separator","docs/components/separator",{"title":205,"path":206,"stem":207,"new":18,"type":19,"children":-1},"Sheet","/docs/components/sheet","docs/components/sheet",{"title":209,"path":210,"stem":211,"new":18,"type":19,"children":-1},"Sidebar","/docs/components/sidebar","docs/components/sidebar",{"title":213,"path":214,"stem":215,"new":18,"type":19,"children":-1},"Skeleton","/docs/components/skeleton","docs/components/skeleton",{"title":217,"path":218,"stem":219,"new":18,"type":19,"children":-1},"Slider","/docs/components/slider","docs/components/slider",{"title":221,"path":222,"stem":223,"new":18,"type":19,"children":-1},"Sonner","/docs/components/sonner","docs/components/sonner",{"title":225,"path":226,"stem":227,"new":18,"type":19,"children":-1},"Spinner","/docs/components/spinner","docs/components/spinner",{"title":229,"path":230,"stem":231,"new":18,"type":19,"children":-1},"Stepper","/docs/components/stepper","docs/components/stepper",{"title":233,"path":234,"stem":235,"new":18,"type":19,"children":-1},"Switch","/docs/components/switch","docs/components/switch",{"title":237,"path":238,"stem":239,"new":18,"type":19,"children":-1},"Table","/docs/components/table","docs/components/table",{"title":241,"path":242,"stem":243,"new":18,"type":19,"children":-1},"Tabs","/docs/components/tabs","docs/components/tabs",{"title":245,"path":246,"stem":247,"new":18,"type":19,"children":-1},"Tags Input","/docs/components/tags-input","docs/components/tags-input",{"title":249,"path":250,"stem":251,"new":18,"type":19,"children":-1},"Textarea","/docs/components/textarea","docs/components/textarea",{"title":253,"path":254,"stem":255,"new":18,"type":19,"children":-1},"Toast","/docs/components/toast","docs/components/toast",{"title":257,"path":258,"stem":259,"new":18,"type":19,"children":-1},"Toggle","/docs/components/toggle","docs/components/toggle",{"title":261,"path":262,"stem":263,"new":18,"type":19,"children":-1},"Toggle Group","/docs/components/toggle-group","docs/components/toggle-group",{"title":265,"path":266,"stem":267,"new":18,"type":19,"children":-1},"Tooltip","/docs/components/tooltip","docs/components/tooltip",{"title":269,"path":270,"stem":271,"new":18,"type":19,"children":-1},"Typography","/docs/components/typography","docs/components/typography","group",{"title":274,"path":275,"stem":276,"children":277,"new":18,"type":272},"Installation","/docs/installation","docs/02.installation",[278,283,287,291,295],{"title":279,"path":280,"stem":281,"new":18,"type":282,"children":-1},"Vite","/docs/installation/vite","docs/installation/01.vite","page",{"title":284,"path":285,"stem":286,"new":18,"type":282,"children":-1},"Nuxt","/docs/installation/nuxt","docs/installation/02.nuxt",{"title":288,"path":289,"stem":290,"new":18,"type":282,"children":-1},"Astro","/docs/installation/astro","docs/installation/03.astro",{"title":292,"path":293,"stem":294,"new":18,"type":282,"children":-1},"Laravel","/docs/installation/laravel","docs/installation/04.laravel",{"title":296,"path":297,"stem":298,"new":18,"type":282,"children":-1},"Manual Installation","/docs/installation/manual","docs/installation/05.manual",{"title":300,"path":301,"stem":302,"children":303,"new":18,"type":272},"Dark Mode","/docs/dark-mode","docs/05.dark-mode",[304,307,310,314],{"title":279,"path":305,"stem":306,"new":18,"type":282,"children":-1},"/docs/dark-mode/vite","docs/dark-mode/01.vite",{"title":284,"path":308,"stem":309,"new":18,"type":282,"children":-1},"/docs/dark-mode/nuxt","docs/dark-mode/02.nuxt",{"title":311,"path":312,"stem":313,"new":18,"type":282,"children":-1},"Vitepress","/docs/dark-mode/vitepress","docs/dark-mode/03.vitepress",{"title":288,"path":315,"stem":316,"new":18,"type":282,"children":-1},"/docs/dark-mode/astro","docs/dark-mode/04.astro",{"title":318,"path":319,"stem":320,"children":321,"new":18,"type":272},"Forms","/docs/forms","docs/forms",[322,326],{"title":323,"path":324,"stem":325,"new":18,"type":282,"children":-1},"VeeValidate","/docs/forms/vee-validate","docs/forms/01.vee-validate",{"title":327,"path":328,"stem":329,"new":18,"type":282,"children":-1},"TanStack Form","/docs/forms/tanstack-form","docs/forms/02.tanstack-form",{"title":331,"path":332,"stem":333,"children":334,"new":18,"type":272},"Registry","/docs/registry","docs/registry/index",[335,336,340,344,348,352],{"title":331,"path":332,"stem":333,"new":18,"type":282,"children":-1},{"title":337,"path":338,"stem":339,"new":18,"type":282,"children":-1},"Examples","/docs/registry/examples","docs/registry/examples",{"title":341,"path":342,"stem":343,"new":18,"type":282,"children":-1},"FAQ","/docs/registry/faq","docs/registry/faq",{"title":345,"path":346,"stem":347,"new":18,"type":282,"children":-1},"Getting Started","/docs/registry/getting-started","docs/registry/getting-started",{"title":349,"path":350,"stem":351,"new":18,"type":282,"children":-1},"registry-item.json","/docs/registry/registry-item-json","docs/registry/registry-item-json",{"title":353,"path":354,"stem":355,"new":18,"type":282,"children":-1},"registry.json","/docs/registry/registry-json","docs/registry/registry-json",{"path":6,"stem":7,"title":357,"type":272,"children":358},"Get Started",[359,363,370,374,378,384,388,392,396,400],{"title":360,"path":361,"stem":362,"new":18,"type":282,"children":-1},"Introduction","/docs/introduction","docs/01.introduction",{"title":274,"path":275,"stem":276,"children":364,"new":18,"type":272},[365,366,367,368,369],{"title":279,"path":280,"stem":281,"new":18,"type":282,"children":-1},{"title":284,"path":285,"stem":286,"new":18,"type":282,"children":-1},{"title":288,"path":289,"stem":290,"new":18,"type":282,"children":-1},{"title":292,"path":293,"stem":294,"new":18,"type":282,"children":-1},{"title":296,"path":297,"stem":298,"new":18,"type":282,"children":-1},{"title":371,"path":372,"stem":373,"new":18,"type":282,"children":-1},"components.json","/docs/components-json","docs/03.components-json",{"title":375,"path":376,"stem":377,"new":18,"type":282,"children":-1},"Theming","/docs/theming","docs/04.theming",{"title":300,"path":301,"stem":302,"children":379,"new":18,"type":272},[380,381,382,383],{"title":279,"path":305,"stem":306,"new":18,"type":282,"children":-1},{"title":284,"path":308,"stem":309,"new":18,"type":282,"children":-1},{"title":311,"path":312,"stem":313,"new":18,"type":282,"children":-1},{"title":288,"path":315,"stem":316,"new":18,"type":282,"children":-1},{"title":385,"path":386,"stem":387,"new":18,"type":282,"children":-1},"CLI","/docs/cli","docs/06.cli",{"title":389,"path":390,"stem":391,"new":18,"type":282,"children":-1},"JavaScript","/docs/javascript","docs/07.javascript",{"title":393,"path":394,"stem":395,"new":18,"type":282,"children":-1},"Figma","/docs/figma","docs/09.figma",{"title":397,"path":398,"stem":399,"new":18,"type":282,"children":-1},"Changelog","/docs/changelog","docs/10.changelog",{"title":401,"path":402,"stem":403,"new":18,"type":282,"children":-1},"Legacy Docs","/docs/legacy","docs/11.legacy",{"repo":405},{"id":406,"name":407,"repo":408,"description":409,"createdAt":410,"updatedAt":411,"pushedAt":412,"stars":413,"watchers":414,"forks":415,"defaultBranch":416},658791894,"shadcn-vue","unovue/shadcn-vue","Vue port of shadcn-ui","2023-06-26T13:53:23Z","2026-04-14T10:18:37Z","2026-04-13T06:37:16Z",9755,38,638,"dev",{"id":418,"title":117,"body":419,"description":862,"extension":863,"links":864,"meta":865,"navigation":867,"new":18,"path":118,"rawbody":868,"seo":869,"stem":119,"__hash__":870},"content/docs/components/form.md",{"type":420,"value":421,"toc":850},"minimark",[422,445,448,451,470,493,498,508,563,571,579,583,593,597,648,651,709,713,719,724,731,740,746,758,762,775],[423,424,426],"callout",{"title":425},"We are not actively developing this component anymore.",[427,428,429,430,434,435,441,442,444],"p",{},"The Form component is an abstraction over the ",[431,432,433],"code",{},"vee-validate"," library. Going forward, we recommend using the ",[436,437,438],"a",{"href":114},[431,439,440],{},"\u003CField />"," component to build forms. See the ",[436,443,117],{"href":319}," documentation for more information.",[427,446,447],{},"Forms are tricky. They are one of the most common things you'll build in a web application, but also one of the most complex.",[427,449,450],{},"Well-designed HTML forms are:",[452,453,454,458,461,464,467],"ul",{},[455,456,457],"li",{},"Well-structured and semantically correct.",[455,459,460],{},"Easy to use and navigate (keyboard).",[455,462,463],{},"Accessible with ARIA attributes and proper labels.",[455,465,466],{},"Has support for client and server side validation.",[455,468,469],{},"Well-styled and consistent with the rest of the application.",[427,471,472,473,480,481,488,489,492],{},"In this guide, we will take a look at building forms with ",[436,474,478],{"href":475,"rel":476},"https://vee-validate.logaretm.com/v4/",[477],"nofollow",[431,479,433],{}," and ",[436,482,485],{"href":483,"rel":484},"https://zod.dev",[477],[431,486,487],{},"zod",". We're going to use a ",[431,490,491],{},"\u003CFormField>"," component to compose accessible forms using Reka UI components.",[494,495,497],"h2",{"id":496},"features","Features",[427,499,500,501,504,505,507],{},"The ",[431,502,503],{},"\u003CForm />"," component is a wrapper around the ",[431,506,433],{}," library. It provides a few things:",[452,509,510,513,520,526,533,536,557],{},[455,511,512],{},"Composable components for building forms.",[455,514,515,516,519],{},"A ",[431,517,518],{},"\u003CFormField />"," component for building controlled form fields.",[455,521,522,523,525],{},"Form validation using ",[431,524,487],{},".",[455,527,528,529,532],{},"Applies the correct ",[431,530,531],{},"aria"," attributes to form fields based on states, handle unique IDs",[455,534,535],{},"Built to work with all Reka UI components.",[455,537,538,539,541,542,549,550,525],{},"Bring your own schema library. We use ",[431,540,487],{}," but you can use any other supported schema validation you want, like ",[436,543,546],{"href":544,"rel":545},"https://github.com/jquense/yup",[477],[431,547,548],{},"yup"," or ",[436,551,554],{"href":552,"rel":553},"https://valibot.dev/",[477],[431,555,556],{},"valibot",[455,558,559],{},[560,561,562],"strong",{},"You have full control over the markup and styling.",[427,564,565,570],{},[436,566,568],{"href":475,"rel":567},[477],[431,569,433],{}," makes use of two flavors to add validation to your forms.",[452,572,573,576],{},[455,574,575],{},"Composition API",[455,577,578],{},"Higher-order components (HOC)",[494,580,582],{"id":581},"anatomy","Anatomy",[584,585,591],"pre",{"className":586,"code":588,"language":589,"meta":590},[587],"language-vue","\u003Ctemplate>\n  \u003CForm>\n    \u003CFormField>\n      \u003CFormItem>\n        \u003CFormLabel />\n        \u003CFormControl>\n        \u003C!-- any Form Input component or native input elements -->\n        \u003C/FormControl>\n        \u003CFormDescription />\n        \u003CFormMessage />\n      \u003C/FormItem>\n    \u003C/FormField>\n  \u003C/Form>\n\u003C/template>\n","vue","",[431,592,588],{"__ignoreMap":590},[494,594,596],{"id":595},"example","Example",[598,599,600,615,632],"tabs",{"default-value":19},[601,602,603,609],"tabs-list",{},[604,605,606],"tabs-trigger",{"value":19},[427,607,608],{},"Component",[604,610,612],{"value":611},"native",[427,613,614],{},"Native",[616,617,618,625],"tabs-content",{"value":19},[619,620,622,624],"h4",{"id":621},"input-component",[431,623,125],{}," Component",[584,626,630],{"className":627,"code":628,"language":589,"meta":629},[587],"\u003Ctemplate>\n  \u003CFormField v-slot=\"{ componentField }\">\n    \u003CFormItem>\n      \u003CFormLabel>Username\u003C/FormLabel>\n      \u003CFormControl>\n        \u003CInput placeholder=\"shadcn\" v-bind=\"componentField\" />\n      \u003C/FormControl>\n      \u003CFormDescription />\n      \u003CFormMessage />\n    \u003C/FormItem>\n  \u003C/FormField>\n\u003C/template>\n","showLineNumbers",[431,631,628],{"__ignoreMap":590},[616,633,634,642],{"value":611},[619,635,637,638,641],{"id":636},"native-input-element","native ",[431,639,640],{},"input"," element",[584,643,646],{"className":644,"code":645,"language":589,"meta":629},[587],"\u003Ctemplate>\n  \u003CFormField v-slot=\"{ field }\">\n    \u003CFormItem>\n      \u003CFormLabel>Username\u003C/FormLabel>\n      \u003CFormControl>\n        \u003Cinput placeholder=\"shadcn\" v-bind=\"field\">\n      \u003C/FormControl>\n      \u003CFormDescription />\n      \u003CFormMessage />\n    \u003C/FormItem>\n  \u003C/FormField>\n\u003C/template>\n",[431,647,645],{"__ignoreMap":590},[494,649,274],{"id":650},"installation",[598,652,654,666,676],{"default-value":653},"cli",[601,655,656,660],{},[604,657,658],{"value":653},[427,659,385],{},[604,661,663],{"value":662},"manual",[427,664,665],{},"Manual",[616,667,668],{"value":653},[584,669,674],{"className":670,"code":672,"language":673,"meta":590},[671],"language-bash","npx shadcn-vue@latest add form\n","bash",[431,675,672],{"__ignoreMap":590},[616,677,678],{"value":662},[679,680,681,687,693,704],"steps",{},[682,683,684],"step",{},[427,685,686],{},"Install the following dependency:",[584,688,691],{"className":689,"code":690,"language":673,"meta":590},[671],"npm install reka-ui vee-validate @vee-validate/zod zod\n",[431,692,690],{"__ignoreMap":590},[682,694,695],{},[427,696,697,698,703],{},"Copy and paste the ",[436,699,702],{"href":700,"rel":701},"https://github.com/unovue/shadcn-vue/tree/dev/apps/v4/registry/new-york-v4/ui/form",[477],"GitHub source code"," into your project.",[682,705,706],{},[427,707,708],{},"Update the import paths to match your project setup.",[494,710,712],{"id":711},"usage","Usage",[584,714,717],{"className":715,"code":716,"language":589,"meta":629},[587],"\u003Cscript setup lang=\"ts\">\nimport {\n  FormControl,\n  FormDescription,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage,\n} from '@/components/ui/form'\n\u003C/script>\n\n\u003Ctemplate>\n  \u003CFormField v-slot=\"{ componentField }\" name=\"username\">\n    \u003CFormItem>\n      \u003CFormLabel>Username\u003C/FormLabel>\n      \u003CFormControl>\n        \u003CInput placeholder=\"shadcn\" v-bind=\"componentField\" />\n      \u003C/FormControl>\n      \u003CFormDescription>\n        This is your public display name.\n      \u003C/FormDescription>\n      \u003CFormMessage />\n    \u003C/FormItem>\n  \u003C/FormField>\n\u003C/template>\n",[431,718,716],{"__ignoreMap":590},[720,721,723],"h3",{"id":722},"create-a-form-schema","Create a form schema",[427,725,726,727,525],{},"Define the shape of your form using a Zod schema. You can read more about using Zod in the ",[436,728,730],{"href":483,"rel":729},[477],"Zod documentation",[427,732,733,734,737,738],{},"Use ",[431,735,736],{},"@vee-validate/zod"," to integrate Zod schema validation with ",[431,739,433],{},[427,741,742,745],{},[431,743,744],{},"toTypedSchema"," also makes the form values and submitted values typed automatically and caters for both input and output types of that schema.",[584,747,756],{"className":748,"code":749,"highlights":750,"language":589,"meta":629},[587],"\u003Cscript setup lang=\"ts\">\nimport { toTypedSchema } from '@vee-validate/zod'\nimport * as z from 'zod'\n\nconst formSchema = toTypedSchema(z.object({\n  username: z.string().min(2).max(50),\n}))\n\u003C/script>\n",[751,752,753,754,755],2,3,5,6,7,[431,757,749],{"__ignoreMap":590},[720,759,761],{"id":760},"define-a-form","Define a form",[427,763,764,765,768,769,771,772,774],{},"Use the ",[431,766,767],{},"useForm"," composable from ",[431,770,433],{}," or use ",[431,773,503],{}," component to create a form.",[598,776,778,789,801,813,817,829,836,840,843],{"default-value":777},"composition",[601,779,780,785],{},[604,781,782],{"value":777},[427,783,784],{},"Composition",[604,786,787],{"value":19},[427,788,608],{},[616,790,791],{"value":777},[584,792,799],{"className":793,"code":794,"highlights":795,"language":589,"meta":629},[587],"\u003Cscript setup lang=\"ts\">\nimport { useForm } from 'vee-validate'\nimport { toTypedSchema } from '@vee-validate/zod'\nimport * as z from 'zod'\n\nimport {\n  FormControl,\n  FormDescription,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage\n} from '@/components/ui/form'\n\nconst formSchema = toTypedSchema(z.object({\n  username: z.string().min(2).max(50),\n}))\n\nconst form = useForm({\n  validationSchema: formSchema,\n})\n\nconst onSubmit = form.handleSubmit((values) => {\n  console.log('Form submitted!', values)\n})\n\u003C/script>\n\n\u003Ctemplate>\n  \u003Cform @submit=\"onSubmit\">\n    ...\n  \u003C/form>\n\u003C/template>\n",[751,796,797,798],19,20,21,[431,800,794],{"__ignoreMap":590},[616,802,803],{"value":19},[584,804,811],{"className":805,"code":806,"highlights":807,"language":589,"meta":629},[587],"\u003Cscript setup lang=\"ts\">\nimport { toTypedSchema } from '@vee-validate/zod'\nimport * as z from 'zod'\nimport {\n  Form,\n  FormControl,\n  FormDescription,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage\n} from '@/components/ui/form'\n\nconst formSchema = toTypedSchema(z.object({\n  username: z.string().min(2).max(50),\n}))\n\nfunction onSubmit(values) {\n  console.log('Form submitted!', values)\n}\n\u003C/script>\n\n\u003Ctemplate>\n  \u003CForm :validation-schema=\"formSchema\" @submit=\"onSubmit\">\n    ...\n  \u003C/Form>\n\u003C/template>\n",[753,808,809,810],24,25,26,[431,812,806],{"__ignoreMap":590},[720,814,816],{"id":815},"build-your-form","Build your form",[427,818,819,820,822,823,825,826,828],{},"Based on last step we can either use ",[431,821,503],{}," component or ",[431,824,767],{}," composable\n",[431,827,767],{}," is recommended because values are typed automatically",[584,830,834],{"className":831,"code":832,"highlights":833,"language":589,"meta":629},[587],"\u003Cscript setup lang=\"ts\">\nimport { toTypedSchema } from '@vee-validate/zod'\nimport { useForm } from 'vee-validate'\nimport * as z from 'zod'\n\nimport { Button } from '@/components/ui/button'\nimport {\n  FormControl,\n  FormDescription,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage,\n} from '@/components/ui/form'\nimport { Input } from '@/components/ui/input'\n\nconst formSchema = toTypedSchema(z.object({\n  username: z.string().min(2).max(50),\n}))\n\nconst form = useForm({\n  validationSchema: formSchema,\n})\n\nconst onSubmit = form.handleSubmit((values) => {\n  console.log('Form submitted!', values)\n})\n\u003C/script>\n\n\u003Ctemplate>\n  \u003Cform @submit=\"onSubmit\">\n    \u003CFormField v-slot=\"{ componentField }\" name=\"username\">\n      \u003CFormItem>\n        \u003CFormLabel>Username\u003C/FormLabel>\n        \u003CFormControl>\n          \u003CInput type=\"text\" placeholder=\"shadcn\" v-bind=\"componentField\" />\n        \u003C/FormControl>\n        \u003CFormDescription>\n          This is your public display name.\n        \u003C/FormDescription>\n        \u003CFormMessage />\n      \u003C/FormItem>\n    \u003C/FormField>\n    \u003CButton type=\"submit\">\n      Submit\n    \u003C/Button>\n  \u003C/form>\n\u003C/template>\n",[751],[431,835,832],{"__ignoreMap":590},[720,837,839],{"id":838},"done","Done",[427,841,842],{},"That's it. You now have a fully accessible form that is type-safe with client-side validation.",[844,845],"component-preview",{"className":846,"name":849},[847,848],"[&_[role=tablist]]:hidden","[&>div>div:first-child]:hidden","InputForm",{"title":590,"searchDepth":751,"depth":751,"links":851},[852,853,854,855,856],{"id":496,"depth":751,"text":497},{"id":581,"depth":751,"text":582},{"id":595,"depth":751,"text":596},{"id":650,"depth":751,"text":274},{"id":711,"depth":751,"text":712,"children":857},[858,859,860,861],{"id":722,"depth":752,"text":723},{"id":760,"depth":752,"text":761},{"id":815,"depth":752,"text":816},{"id":838,"depth":752,"text":839},"Building forms with VeeValidate and Zod.","md",null,{"primitive":866,"component":867},"https://vee-validate.logaretm.com/v4/guide/overview/",true,"---\ntitle: Form\ndescription: Building forms with VeeValidate and Zod.\nprimitive: https://vee-validate.logaretm.com/v4/guide/overview/\ncomponent: true\n---\n\n::callout{title=\"We are not actively developing this component anymore.\"}\n\nThe Form component is an abstraction over the `vee-validate` library. Going forward, we recommend using the [`\u003CField />`](/docs/components/field) component to build forms. See the [Form](/docs/forms) documentation for more information.\n\n::\n\nForms are tricky. They are one of the most common things you'll build in a web application, but also one of the most complex.\n\nWell-designed HTML forms are:\n\n- Well-structured and semantically correct.\n- Easy to use and navigate (keyboard).\n- Accessible with ARIA attributes and proper labels.\n- Has support for client and server side validation.\n- Well-styled and consistent with the rest of the application.\n\nIn this guide, we will take a look at building forms with [`vee-validate`](https://vee-validate.logaretm.com/v4/) and [`zod`](https://zod.dev). We're going to use a `\u003CFormField>` component to compose accessible forms using Reka UI components.\n\n## Features\n\nThe `\u003CForm />` component is a wrapper around the `vee-validate` library. It provides a few things:\n\n- Composable components for building forms.\n- A `\u003CFormField />` component for building controlled form fields.\n- Form validation using `zod`.\n- Applies the correct `aria` attributes to form fields based on states, handle unique IDs\n- Built to work with all Reka UI components.\n- Bring your own schema library. We use `zod` but you can use any other supported schema validation you want, like [`yup`](https://github.com/jquense/yup) or [`valibot`](https://valibot.dev/).\n- **You have full control over the markup and styling.**\n\n[`vee-validate`](https://vee-validate.logaretm.com/v4/) makes use of two flavors to add validation to your forms.\n- Composition API\n- Higher-order components (HOC)\n\n## Anatomy\n\n```vue\n\u003Ctemplate>\n  \u003CForm>\n    \u003CFormField>\n      \u003CFormItem>\n        \u003CFormLabel />\n        \u003CFormControl>\n        \u003C!-- any Form Input component or native input elements -->\n        \u003C/FormControl>\n        \u003CFormDescription />\n        \u003CFormMessage />\n      \u003C/FormItem>\n    \u003C/FormField>\n  \u003C/Form>\n\u003C/template>\n```\n\n## Example\n\n::tabs{default-value=\"component\"}\n\n  ::tabs-list\n\n    ::tabs-trigger{value=\"component\"}\n    Component\n    ::\n\n    ::tabs-trigger{value=\"native\"}\n    Native\n    ::\n\n  ::\n\n  ::tabs-content{value=\"component\"}\n\n  #### `Input` Component\n\n  ```vue showLineNumbers\n  \u003Ctemplate>\n    \u003CFormField v-slot=\"{ componentField }\">\n      \u003CFormItem>\n        \u003CFormLabel>Username\u003C/FormLabel>\n        \u003CFormControl>\n          \u003CInput placeholder=\"shadcn\" v-bind=\"componentField\" />\n        \u003C/FormControl>\n        \u003CFormDescription />\n        \u003CFormMessage />\n      \u003C/FormItem>\n    \u003C/FormField>\n  \u003C/template>\n  ```\n\n  ::\n\n  ::tabs-content{value=\"native\"}\n\n  #### native `input` element\n\n  ```vue showLineNumbers\n  \u003Ctemplate>\n    \u003CFormField v-slot=\"{ field }\">\n      \u003CFormItem>\n        \u003CFormLabel>Username\u003C/FormLabel>\n        \u003CFormControl>\n          \u003Cinput placeholder=\"shadcn\" v-bind=\"field\">\n        \u003C/FormControl>\n        \u003CFormDescription />\n        \u003CFormMessage />\n      \u003C/FormItem>\n    \u003C/FormField>\n  \u003C/template>\n  ```\n\n  ::\n::\n\n## Installation\n\n::tabs{default-value=\"cli\"}\n\n  ::tabs-list\n\n    ::tabs-trigger{value=\"cli\"}\n    CLI\n    ::\n\n    ::tabs-trigger{value=\"manual\"}\n    Manual\n    ::\n\n  ::\n\n  ::tabs-content{value=\"cli\"}\n\n  ```bash\n  npx shadcn-vue@latest add form\n  ```\n\n  ::\n\n  ::tabs-content{value=\"manual\"}\n\n    ::steps\n      ::step\n      Install the following dependency:\n      ::\n\n      ```bash\n      npm install reka-ui vee-validate @vee-validate/zod zod\n      ```\n\n      ::step\n      Copy and paste the [GitHub source code](https://github.com/unovue/shadcn-vue/tree/dev/apps/v4/registry/new-york-v4/ui/form) into your project.\n      ::\n\n      ::step\n      Update the import paths to match your project setup.\n      ::\n    ::\n\n  ::\n\n::\n\n## Usage\n\n```vue showLineNumbers\n\u003Cscript setup lang=\"ts\">\nimport {\n  FormControl,\n  FormDescription,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage,\n} from '@/components/ui/form'\n\u003C/script>\n\n\u003Ctemplate>\n  \u003CFormField v-slot=\"{ componentField }\" name=\"username\">\n    \u003CFormItem>\n      \u003CFormLabel>Username\u003C/FormLabel>\n      \u003CFormControl>\n        \u003CInput placeholder=\"shadcn\" v-bind=\"componentField\" />\n      \u003C/FormControl>\n      \u003CFormDescription>\n        This is your public display name.\n      \u003C/FormDescription>\n      \u003CFormMessage />\n    \u003C/FormItem>\n  \u003C/FormField>\n\u003C/template>\n```\n\n### Create a form schema\n\n  Define the shape of your form using a Zod schema. You can read more about using Zod in the [Zod documentation](https://zod.dev).\n\n  Use `@vee-validate/zod` to integrate Zod schema validation with `vee-validate`\n\n  `toTypedSchema` also makes the form values and submitted values typed automatically and caters for both input and output types of that schema.\n\n  ```vue showLineNumbers {2-3,5-7}\n  \u003Cscript setup lang=\"ts\">\n  import { toTypedSchema } from '@vee-validate/zod'\n  import * as z from 'zod'\n\n  const formSchema = toTypedSchema(z.object({\n    username: z.string().min(2).max(50),\n  }))\n  \u003C/script>\n  ```\n\n### Define a form\n\n  Use the `useForm` composable from `vee-validate` or use `\u003CForm />` component to create a form.\n\n  ::tabs{default-value=\"composition\"}\n\n    ::tabs-list\n\n      ::tabs-trigger{value=\"composition\"}\n      Composition\n      ::\n\n      ::tabs-trigger{value=\"component\"}\n      Component\n      ::\n\n    ::\n\n    ::tabs-content{value=\"composition\"}\n\n    ```vue showLineNumbers {2,19-21}\n    \u003Cscript setup lang=\"ts\">\n    import { useForm } from 'vee-validate'\n    import { toTypedSchema } from '@vee-validate/zod'\n    import * as z from 'zod'\n\n    import {\n      FormControl,\n      FormDescription,\n      FormField,\n      FormItem,\n      FormLabel,\n      FormMessage\n    } from '@/components/ui/form'\n\n    const formSchema = toTypedSchema(z.object({\n      username: z.string().min(2).max(50),\n    }))\n\n    const form = useForm({\n      validationSchema: formSchema,\n    })\n\n    const onSubmit = form.handleSubmit((values) => {\n      console.log('Form submitted!', values)\n    })\n    \u003C/script>\n\n    \u003Ctemplate>\n      \u003Cform @submit=\"onSubmit\">\n        ...\n      \u003C/form>\n    \u003C/template>\n    ```\n\n    ::\n\n    ::tabs-content{value=\"component\"}\n\n    ```vue showLineNumbers {5,24-26}\n    \u003Cscript setup lang=\"ts\">\n    import { toTypedSchema } from '@vee-validate/zod'\n    import * as z from 'zod'\n    import {\n      Form,\n      FormControl,\n      FormDescription,\n      FormField,\n      FormItem,\n      FormLabel,\n      FormMessage\n    } from '@/components/ui/form'\n\n    const formSchema = toTypedSchema(z.object({\n      username: z.string().min(2).max(50),\n    }))\n\n    function onSubmit(values) {\n      console.log('Form submitted!', values)\n    }\n    \u003C/script>\n\n    \u003Ctemplate>\n      \u003CForm :validation-schema=\"formSchema\" @submit=\"onSubmit\">\n        ...\n      \u003C/Form>\n    \u003C/template>\n    ```\n\n    ::\n\n### Build your form\n\n  Based on last step we can either use `\u003CForm />` component or `useForm` composable\n  `useForm` is recommended because values are typed automatically\n\n  ```vue showLineNumbers {2}\n  \u003Cscript setup lang=\"ts\">\n  import { toTypedSchema } from '@vee-validate/zod'\n  import { useForm } from 'vee-validate'\n  import * as z from 'zod'\n\n  import { Button } from '@/components/ui/button'\n  import {\n    FormControl,\n    FormDescription,\n    FormField,\n    FormItem,\n    FormLabel,\n    FormMessage,\n  } from '@/components/ui/form'\n  import { Input } from '@/components/ui/input'\n\n  const formSchema = toTypedSchema(z.object({\n    username: z.string().min(2).max(50),\n  }))\n\n  const form = useForm({\n    validationSchema: formSchema,\n  })\n\n  const onSubmit = form.handleSubmit((values) => {\n    console.log('Form submitted!', values)\n  })\n  \u003C/script>\n\n  \u003Ctemplate>\n    \u003Cform @submit=\"onSubmit\">\n      \u003CFormField v-slot=\"{ componentField }\" name=\"username\">\n        \u003CFormItem>\n          \u003CFormLabel>Username\u003C/FormLabel>\n          \u003CFormControl>\n            \u003CInput type=\"text\" placeholder=\"shadcn\" v-bind=\"componentField\" />\n          \u003C/FormControl>\n          \u003CFormDescription>\n            This is your public display name.\n          \u003C/FormDescription>\n          \u003CFormMessage />\n        \u003C/FormItem>\n      \u003C/FormField>\n      \u003CButton type=\"submit\">\n        Submit\n      \u003C/Button>\n    \u003C/form>\n  \u003C/template>\n  ```\n\n### Done\n\n  That's it. You now have a fully accessible form that is type-safe with client-side validation.\n\n  ::component-preview\n  ---\n  name: InputForm\n  class: '[&_[role=tablist]]:hidden [&>div>div:first-child]:hidden'\n  ---\n  ::\n\n::\n\n\u003C!-- ## Extras\n\nThis example shows how to add motion to your forms with [Formkit AutoAnimate](https://auto-animate.formkit.com/)\n\n**Note:** You need to install `@formkit/auto-animate` to use this feature:\n\n```bash\nnpm install @formkit/auto-animate\n```\n\n::component-preview\n---\nname: InputFormAutoAnimate\n---\n:: -->\n",{"title":117,"description":862},"PUmg121XdEVgH6NDOQ0G2ptPggz9T7cSq4QFvhZC9Zw",[872,873],{"title":113,"path":114,"stem":115,"children":-1},{"title":121,"path":122,"stem":123,"children":-1},1776258642151]