Field, label and form
The frame around one form control: Field ties a FieldLabel, a FieldDescription and a FieldError to it, and Fieldset groups fields under a legend.
ui.field
components/ui/field.tsxUse case
Use it for every control in a form, so each has its label, its hint and its error in the same place: the company name and email on a new client form, the due date and terms on an invoice, a Delivery section on an order form. Field marks its control invalid and shows the error; Fieldset with a FieldsetLegend titles a section. When the server answers with errors by field name, Base UI's Form (components/ui/form) takes them through its errors prop, keyed by each Field's name.
Use it when
- Any input, text area, number field or select in a form
- A hint under a control (As it appears on invoices.)
- An error under a control after it is checked
- A titled section of a form (Fieldset)
Use something else when
- An error about the whole form, not one control (Could not save): Alert
- A short form that opens over the page: Dialog
- A single search box above a list: Search field
Examples
Code
Import
import { Button } from "@/components/ui/button"
import { Field, FieldDescription, FieldError, FieldLabel } from "@/components/ui/field"
import { Fieldset, FieldsetLegend } from "@/components/ui/fieldset"
import { Input } from "@/components/ui/input"Usage
<form className="grid gap-6" onSubmit={save}>
<Fieldset className="grid gap-5">
<FieldsetLegend className="text-[15px] font-medium">Your company</FieldsetLegend>
<Field>
<FieldLabel>Company name</FieldLabel>
<Input name="company" placeholder="Atelier Nord" />
<FieldDescription>As it appears on invoices.</FieldDescription>
</Field>
<Field invalid={Boolean(emailError)}>
<FieldLabel>Email</FieldLabel>
<Input name="email" type="email" placeholder="bonjour@ateliernord.ca" />
{emailError && <FieldError match>{emailError}</FieldError>}
</Field>
</Fieldset>
<div className="flex justify-end gap-2">
<Button variant="ghost">Cancel</Button>
<Button type="submit">Save Changes</Button>
</div>
</form>Rules
- One control per Field; the Field ties the FieldLabel to it, so no htmlFor is needed.
- Show an error by setting invalid on the Field and rendering FieldError match only while there is an error (match always shows it).
- Labels, legends and descriptions in sentence case; the buttons in Title Case, the submit one with type="submit".
- FieldsetLegend is semibold by default: give it className="text-[15px] font-medium", as the showcase does, since weights stop at 500.
- A label for something outside a Field is Label (components/ui/label) with htmlFor.