WCAG 2.1 AA compliance
Form fields satisfy these accessibility requirements out of the box.
Label association
Every integrated field (FormInput, FormSelect, etc.) generates a unique id via useId() and passes it to both the FormLabel (htmlFor) and the control (id). This ensures screen readers announce the label when the field receives focus.
Error announcements
FormMessage renders with role="alert", which triggers an immediate screen-reader announcement when it appears. The control links to the error via aria-describedby, so the error is also announced on focus.
Required fields
When required is set, FormLabel renders a visual asterisk and aria-required is set on the control. Both signals are present — the asterisk alone is insufficient for screen readers.
Description association
When a description prop is provided and the field has no error, aria-describedby links to the description element. When an error is present, it takes priority over the description.
Keyboard navigation
- Tab moves between form fields in source order.
- Enter on a
FormSelectorFormRadioGroupopens the dropdown or activates the option. - Escape closes open select dropdowns.
- Space toggles
FormCheckboxandFormSwitch.
Focus management
- On validation error, the error message appears without moving focus. Users can tab back to correct the field.
- In multi-step forms, focus should be managed at the application level (move focus to the first field of the new step).
FormFieldArray
- Each array item is wrapped in a bordered container for visual grouping.
- The "Add" button has a visible text label (
addLabelprop). - Remove buttons are rendered per-item by the consumer's
renderFieldcallback — ensure they have descriptive text oraria-label.
FormActions
- The submit button auto-disables when the form is invalid (
canSubmit: false) or submitting, preventing double-submits. - Button text changes to "Submitting..." during submission, providing visual feedback.
- Both buttons remain in the tab order when disabled.
Audit checklist
- Every field has a visible label — no placeholder-only fields.
-
aria-describedbylinks to error or description, never both simultaneously. - Error messages use
role="alert"for immediate announcement. -
aria-requiredis set on required controls. -
aria-invalidis set (viainvalidprop) on controls with errors. - Touch targets are at least 44px when using
size="lg"inputs. - Color contrast on error text meets 4.5:1.
- Field array remove buttons have descriptive labels.
- FormActions submit button is disabled (not hidden) when form is invalid.