How to build an accessible Field in React

Generates stable ids with useId and links them through htmlFor and aria-describedby; the error carries role="alert" so it is announced on appearance, and aria-invalid marks the control invalid for assistive tech

When to use a Field

When not to use it

Accessibility

Role group, verified at WCAG 2.2-AA.

Common mistakes

Avoid: <Field label="Email"><Input label="Email" /></Field>

Prefer: <Field label="Email"><Input /></Field>

Field owns the label; a labelled child (Input, Textarea, NativeSelect, …) renders a SECOND <label> for the same control. Omit the child's label inside a Field (dev builds warn).

Avoid: <Field label="Email"><Input /><Input /></Field>

Prefer: <Field label="Email"><Input /></Field>

Field clones exactly one child control to inject its id and aria wiring; multiple children break the association

Avoid: <div><label>Email</label><input aria-invalid /><span>Error</span></div>

Prefer: <Field label="Email" error="Error"><Input /></Field>

Hand-wired markup easily drifts: missing ids, no role="alert", mismatched aria-describedby — Field keeps them in sync

Example

<Field label="Email"><Input type="email" /></Field>

See the full Field reference →