WeDanceDesign System

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

Your full name

We'll never share your email

Your feedback or question

Get updates about new features and events

Select a category

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:

Component
Description
Example
Input
Standard text input field
Textarea
Multi-line text input
Select
Dropdown selection field
Checkbox
Single checkbox for boolean values
RadioGroup
Radio button group for mutually exclusive options
PhoneInput
Phone number input with country code selection

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:

Personal
Contact
Review

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:

Items

Item 1