Field puts a label above a control, a hint under it and an error when there is one, and connects them. The control gets its id, aria-describedby, aria-invalid and aria-required from the field, merged with any it already has, so a screen reader hears the error the moment it appears.
- The label's htmlFor points at the control's id. The control keeps its own id; a control without one gets a generated id.
- aria-describedby lists the control's own description first, then the error, then the hint.
- While error is set the control is aria-invalid. Input, Textarea and the fields built on them, such as Select, PasswordInput and NumberInput, also draw their error styling, with no separate error prop.
- required adds aria-required and an asterisk after the label. The asterisk is hidden from screen readers so it is not read out twice.
The hint stays visible while the error shows, so the instruction is still there when the user goes back to fix the value.
Native elements and third-party controls get the same props. For a control that needs them somewhere other than its root, pass a function: it receives the props to spread.
A custom control can also read the field from context with useField(), which returns the id, invalid, required and describedBy of the enclosing field, or null outside one.
A Field takes span like any other field, and lays out in a Form grid. With density="stacked" the controls still fuse; the labels and messages sit outside the group's border.