Field
Field lines up a label, a control, a hint, and an error, so every row of a form reads the same way.
When to use it
Wrap any form control that needs a visible label, a hint, or an error in Field. It owns the layout and spacing; your form still owns validation.
Group related fields with FieldSet and FieldLegend. Switch a row to horizontal when the label and the control should sit side by side, as in settings.
How it behaves
Field provides layout and styling; keep validation in your form. It does not automatically associate labels, hints, or errors. Set htmlFor/id and aria-describedby explicitly.
Use FieldSet with FieldLegend for a semantic group, FieldGroup for spacing, and FieldContent to pair a label with its description.
Field supports vertical, horizontal, and responsive orientations. Responsive fields switch layout at the FieldGroup container breakpoint.
Use data-invalid on Field and aria-invalid on the control. FieldError accepts children or an errors array, deduplicates messages, and announces them with role=alert.
Use disabled on controls and data-disabled on Field for styling. FieldLabel can wrap a Field with FieldTitle to make a selectable card with visible focus.
Labels and titles use label-md; descriptions and errors use body-sm. Legends use heading-20, or label-md with variant=label. Override roles through className while shared typography tokens remain the source of truth.
The registry item includes Label and Separator. Install controls such as Input, Checkbox, or Select separately when composing your form. Existing control motion is preserved.
Build it
Add it with the shadcn CLI:
1pnpm dlx shadcn@latest add https://jzbui.com/r/field.json https://jzbui.com/r/input.jsonA complete example. Change the values to fit your product:
1234567891011121314import { Field, FieldDescription, FieldGroup, FieldLabel, FieldLegend, FieldSet } from "@/components/ui/field"import { Input } from "@/components/ui/input"
<FieldSet> <FieldLegend>Profile</FieldLegend> <FieldDescription>Choose how you appear to your team.</FieldDescription> <FieldGroup> <Field> <FieldLabel htmlFor="display-name">Display name</FieldLabel> <Input id="display-name" name="displayName" autoComplete="name" aria-describedby="name-hint" /> <FieldDescription id="name-hint">Use the name your teammates know.</FieldDescription> </Field> </FieldGroup></FieldSet>The full source is yours to edit once installed: