Form Patterns
Forms allow users to input and submit data. This guide covers form patterns, validation, and best practices using vee-validate with zod for form validation.
Form Architecture
The WeDance design system uses the following components for building forms:
- vee-validate - Form validation library that provides components and functions to handle form state
- zod - Schema validation library used to define form schemas
- Form Components - Reusable UI components for form inputs (Input, Textarea, Select, etc.)
- FormField - A wrapper component that connects the form context to individual form controls
The form component hierarchy
FormField └── FormItem ├── FormLabel ├── FormControl │ └── Input/Select/Checkbox/etc. ├── FormDescription └── FormMessage
Schema Validation with Zod
All form schemas should be defined in the schemas
folder using zod. Here's an example schema:
import * as z from 'zod' export const contactSchema = z.object({ name: z.string().min(2, 'Name must be at least 2 characters'), email: z.string().email('Please enter a valid email address'), message: z.string().min(10, 'Message must be at least 10 characters'), newsletter: z.boolean().default(false), category: z.enum(['feedback', 'support', 'feature']), })
Basic Form Example
Here's a basic example of a form using vee-validate with zod:
<script setup lang="ts"> import { useForm } from 'vee-validate' import { toTypedSchema } from '@vee-validate/zod' import { toast } from 'vue-sonner' import { contactSchema } from '~/schemas/contact' const form = useForm({ validationSchema: toTypedSchema(contactSchema), }) const onSubmit = form.handleSubmit( async (values) => { // Handle successful submit toast.success('Form submitted successfully!') }, (e) => { // Handle validation errors toast.error('Please fix the errors in the form.') } ) </script> <template> <form @submit="onSubmit" class="space-y-6"> <FormField v-slot="{ componentField }" name="name"> <FormItem> <FormLabel>Name</FormLabel> <FormControl> <Input v-bind="componentField" /> </FormControl> <FormDescription>Your full name</FormDescription> <FormMessage /> </FormItem> </FormField> <!-- Other form fields... --> <Button type="submit">Submit</Button> </form> </template>
Live Example
Form Layouts
standard
Default stacked layout with labels above inputs
Stacked layout example
horizontal
Layout with labels beside inputs, great for wider screens
Horizontal layout example
grid
Grid layout for multiple fields in columns
compact
Compact layout with smaller spacing and optional labels
Form Field Types
WeDance Design System provides various form field components to handle different input types:
Best Practices
Form Organization
- Group related fields together
- Order fields in a logical sequence
- Use clear section headings for longer forms
- Consider multi-step forms for complex processes
Validation
- Use zod schemas for all form validation
- Provide clear error messages
- Validate in real-time for critical fields
- Show validation errors after the user has interacted with the field
Accessibility
- Always use labels for form fields
- Provide descriptive error messages
- Ensure keyboard navigation works properly
- Use ARIA attributes when necessary
- Test forms with screen readers and keyboard-only navigation
Performance
- Debounce validation for fields that trigger expensive operations
- Consider lazy loading complex form components that aren't initially visible
- Use v-model with caution in large forms, prefer vee-validate's state management
Common Form Patterns
Multi-step Forms
For complex forms, consider using a step-by-step approach:
Step content would appear here
Inline Validation
Validate fields as the user types or when they lose focus:
We'll validate this as you type
Form Arrays
For repeatable sections like adding multiple items: