Form
Fields, checks and errors that say what to fix — built on react-hook-form, or by hand as in the preview.
Preview
Usage
import { useForm } from "react-hook-form";
import {
Form, FormField, FormItem, FormLabel, FormControl, FormDescription, FormMessage,
Input, Checkbox, Button,
} from "zostel-ui";
const form = useForm({ defaultValues: { email: "", news: false } });
<Form {...form}>
<form onSubmit={form.handleSubmit(send)} className="space-y-4">
<FormField
control={form.control}
name="email"
rules={{ required: "Add an email." }}
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl><Input type="email" placeholder="you@example.com" {...field} /></FormControl>
<FormDescription>We'll write when your bed is ready.</FormDescription>
<FormMessage />
</FormItem>
)}
/>
{/* a Checkbox (or Switch, RadioGroupItem) takes FormControl's id and aria-labelledby: FormLabel names it */}
<FormField
control={form.control}
name="news"
render={({ field }) => (
<FormItem className="flex items-center gap-2 space-y-0">
<FormControl><Checkbox checked={field.value} onCheckedChange={field.onChange} /></FormControl>
<FormLabel>Send me news from the road</FormLabel>
</FormItem>
)}
/>
<Button type="submit">Send</Button>
</form>
</Form>Parts
| Prop | Type | Default | Description |
|---|---|---|---|
Form | FormProvider | — | Spread the useForm() result into it. |
FormField | { control, name, rules?, render } | — | One field (react-hook-form Controller). |
FormItem | div | — | Groups a label, control, description and message; links their ids. |
FormLabel | Label | — | Turns destructive when the field has an error. |
FormControl | Slot | — | Wraps the control (an Input, a Checkbox, a Switch, a RadioGroupItem): gives it the field’s id (FormLabel’s htmlFor) and, with a FormLabel in the item, aria-labelledby, so the label names it the way axe counts too; sets aria-invalid and aria-describedby. |
FormDescription | p | — | A hint under the field. |
FormMessage | p | — | The field’s error, when there is one. |
useFormField | hook | — | The ids and state of the field it is used in. |
FormFormProviderSpread the useForm() result into it.
FormField{ control, name, rules?, render }One field (react-hook-form Controller).
FormItemdivGroups a label, control, description and message; links their ids.
FormLabelLabelTurns destructive when the field has an error.
FormControlSlotWraps the control (an Input, a Checkbox, a Switch, a RadioGroupItem): gives it the field’s id (FormLabel’s htmlFor) and, with a FormLabel in the item, aria-labelledby, so the label names it the way axe counts too; sets aria-invalid and aria-describedby.
FormDescriptionpA hint under the field.
FormMessagepThe field’s error, when there is one.
useFormFieldhookThe ids and state of the field it is used in.