Field
Form field wrapper that wires label, description and error to any control with stable ids — no more hand-matched htmlFor.
Preview
Live preview
We only use it for billing receipts.
Keep it under 280 characters.
Usage
Examples
Checkbox inside a field
One email per release, no marketing.
<Field
label="Subscribe to the changelog"
description="One email per release, no marketing."
>
{(field) => <Checkbox {...field} />}
</Field>Grouping fields
<FieldGroup label="Billing details">
<Field label="Card number">
{(field) => <Input {...field} inputMode="numeric" placeholder="4242 4242 4242 4242" />}
</Field>
<Field label="Postal code">
{(field) => <Input {...field} placeholder="10115" />}
</Field>
</FieldGroup>Clean vs invalid
Already taken.
<Field label="Workspace slug">
{(field) => <Input {...field} defaultValue="acme" />}
</Field>
<Field label="Workspace slug" error="Already taken.">
{(field) => <Input {...field} defaultValue="acme" />}
</Field>Reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| label | ReactNode | — | Visible label text. The Field generates the id and points htmlFor at it. |
| description | ReactNode | — | Helper text under the control, linked with aria-describedby. |
| error | ReactNode | — | Validation message under the control. Sets aria-invalid and data-invalid, and is announced first in aria-describedby. |
| required | boolean | — | Adds the native required flag to the control plus a decorative asterisk. |
| disabled | boolean | — | Mirrored into the injected control props. |
| children(required) | (field: FieldControlProps) => ReactNode | — | Render the control with the injected props: id, aria-describedby, aria-invalid, required, disabled. |
| className | string | — | Merged onto the wrapper — default is a vertical grid with gap-2. |
Accessibility
Accessibility notes
- The render prop is what makes the wiring safe: the generated id matches the label's htmlFor, and aria-describedby always points at real nodes.
- Errors are listed first in aria-describedby, so screen readers read the problem before the hint.
- The required asterisk is aria-hidden — the native required flag carries the semantics to assistive tech.
- One Field wraps one control. For sets of related inputs use FieldGroup, which renders role=group when you pass a label.
- You can still manage ids yourself with plain Label + Input; Field just removes the bookkeeping.