Components

Form

A thin, accessible layer over react-hook-form that wires labels, controls, descriptions, and validation messages together with the correct ARIA relationships.

Basic usage

Spread the useForm() result onto Form, then drive each input through a FormField render prop.

This is your public display name.

Validation

Pass rules to a field and submit empty — FormMessage surfaces the error and the control flips to its invalid state.

Props

PropTypeDefaultDescription
FormFormProviderContext provider — spread the object returned by useForm() onto it to wire the tree to react-hook-form.
FormFieldrequiredControllerPropsConnects a single field. Requires control and name; render receives a field object to spread onto your input.
FormField.namerequiredstringThe form field key registered with react-hook-form.
FormField.controlrequiredControlThe control object from useForm() that the field binds to.
FormField.renderrequired({ field }) => ReactNodeRender prop that returns the field UI; spread field onto the input.
FormItemReact.ComponentProps<'div'>Grid wrapper that scopes a unique id used to link label, control, description, and message.
FormLabelLabelPrimitive.RootLabel auto-linked to the control via htmlFor; turns destructive when the field has an error.
FormControlSlotSlot that forwards id, aria-describedby, and aria-invalid onto its single input child.
FormDescriptionReact.ComponentProps<'p'>Muted helper text referenced by the control via aria-describedby.
FormMessageReact.ComponentProps<'p'>Renders the field's validation error, or children when there is no error. Renders nothing when empty.

Accessibility

  • FormLabel sets htmlFor to the generated control id, so clicking the label focuses the input and screen readers announce the pairing.
  • FormControl wires aria-describedby to the description and, when invalid, the error message — both are announced for the focused field.
  • When a field has an error, the control receives aria-invalid="true" and the label turns destructive, conveying state beyond color alone.
  • Every id is derived from React.useId() per FormItem, so labels and messages stay correctly associated even with many fields on the page.