Form
React Hook Form integration with accessible labels and validation
Usage
tsx
import { Form, FormItem, FormLabel, FormControl, FormDescription, FormMessage } from '@tryvienna/ui'
<Form {...form}>
<form onSubmit={form.handleSubmit(() => {})} className="grid gap-6 w-96">
<FormField
control={form.control}
name="username"
rules={{ required: 'Username is required' }}
render={({ field }) => (
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input placeholder="johndoe" {...field} />
</FormControl>
<FormDescription>Your public display name.</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="email"
rules={{
required: 'Email is required',
pattern: { value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: 'Invalid email address' },
}}
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input type="email" placeholder="john@example.com" {...field} />
</FormControl>
<FormDescription>We'll never share your email.</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="bio"
render={({ field }) => (
<FormItem>
<FormLabel>Bio</FormLabel>
<FormControl>
<Textarea placeholder="Tell us about yourself..." {...field} />
</FormControl>
<FormDescription>Brief description for your profile.</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Submit</Button>
</form>
</Form>Examples
Simple Form
tsx
<Form {...form}>
<form onSubmit={form.handleSubmit(() => {})} className="grid gap-6 w-96">
<FormField
control={form.control}
name="username"
rules={{ required: 'Username is required' }}
render={({ field }) => (
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input placeholder="johndoe" {...field} />
</FormControl>
<FormDescription>Your public display name.</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="email"
rules={{
required: 'Email is required',
pattern: { value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: 'Invalid email address' },
}}
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input type="email" placeholder="john@example.com" {...field} />
</FormControl>
<FormDescription>We'll never share your email.</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="bio"
render={({ field }) => (
<FormItem>
<FormLabel>Bio</FormLabel>
<FormControl>
<Textarea placeholder="Tell us about yourself..." {...field} />
</FormControl>
<FormDescription>Brief description for your profile.</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Submit</Button>
</form>
</Form>With Validation Errors
tsx
<Form {...form}>
<form className="grid gap-6 w-96">
<FormField
control={form.control}
name="name"
rules={{
required: 'Name is required',
minLength: { value: 2, message: 'Min 2 characters' },
}}
render={({ field }) => (
<FormItem>
<FormLabel>Name</FormLabel>
<FormControl>
<Input placeholder="Your name" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="email"
rules={{
required: 'Email is required',
pattern: { value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: 'Invalid email address' },
}}
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input type="email" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Submit</Button>
</form>
</Form>With Checkbox
tsx
<Form {...form}>
<form onSubmit={form.handleSubmit(() => {})} className="grid gap-6 w-96">
<FormField
control={form.control}
name="terms"
rules={{ validate: (v) => v === true || 'You must accept the terms' }}
render={({ field }) => (
<FormItem>
<div className="flex items-center gap-2">
<FormControl>
<Checkbox checked={field.value} onCheckedChange={field.onChange} />
</FormControl>
<FormLabel>Accept terms and conditions</FormLabel>
</div>
<FormDescription>
You agree to our Terms of Service and Privacy Policy.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Continue</Button>
</form>
</Form>API Reference
FormItem
Also accepts all props from div.
FormLabel
Also accepts all props from LabelPrimitive.Root.
FormControl
Also accepts all props from Slot.
FormDescription
Also accepts all props from p.
FormMessage
Also accepts all props from p.
Data Attributes
| Component | data-slot |
|---|---|
Form | "form-item" |
FormItem | "form-item" |
FormLabel | "form-label" |
FormControl | "form-control" |
FormDescription | "form-description" |
FormMessage | "form-message" |