Skip to content

Forms

Field

A labelled form row: label, control, and the one message below it.

Examples

states

We never share it.

Name is required.

Markdown is fine.

Notes

A labelled form row: label, control, and the one message below it.

The visible message is only half of accessible validation — it must also reach the control. This wires aria-describedby, aria-required and aria-invalid onto the single control child so the requirement and the error are announced, not merely drawn (WCAG 1.3.1 / 3.3.1 / 4.1.2).

An earlier version derived the message id from htmlFor, which meant a caller who left htmlFor off got a hint that was rendered and never announced — the failure was invisible in the browser and total for a screen reader. The id is now generated when it is not supplied.

hint and error are one slot, not two stacked messages: when a field is wrong, the thing to read is what is wrong with it.

Props

Field props
PropTypeDefaultDescription
childrenrequiredReactNode
errorReactNodeValidation message; takes precedence over `hint` when present.
hintReactNodeHelper copy shown below the control when there is no `error`.
htmlForstringThe control's `id`. Optional: when omitted, the field generates one and puts it on the control child itself, so the label still points at something. Pass it explicitly when the id has to be stable across renders — a form library referencing it by name, say.
labelReactNodeVisible label text; renders a `--danger` asterisk when `required`.
requiredboolean

Also accepts everything in HTMLAttributes<HTMLDivElement>. Those are forwarded to the underlying element and are not listed row by row.

Accessibility

  • Generates an id when none is given, so the label always points at something.
  • Wires aria-describedby, aria-required and aria-invalid onto the control, so validation is announced and not merely drawn.
  • hint and error are one slot: when a field is wrong, the thing to read is what is wrong with it.