FormErrorSummary
Review validation errors
Render the summary after validation finds errors. Each error needs a stable unique id, a readable message, and the targetId of its control. Focus the summary ref after a failed submission so someone can review the errors before choosing a field.
Choose Check form with empty fields, then activate the inspection-reference error. The example reveals Schedule before focusing its input. Validation feedback is supplied by the form; the summary does not validate or save values.
Focus a visible control
Without onErrorSelect, Enter, Space or pointer activation focuses the exact target element by ID. Use Field controlId to give a library control a stable target.
const errors = [
{ id: "name-required", message: "Enter an equipment name.", targetId: "resource-name" },
];
<FormErrorSummary ref={summaryRef} errors={errors} />;
<Field controlId="resource-name" label="Name" error="Enter an equipment name.">
<Input />
</Field>;
Missing, hidden or disabled targets cannot be focused automatically. Supply a handler when the target needs to be revealed or replaced.
Reveal a hidden step, then focus
onErrorSelect replaces default focus behavior. Update the visible step, then focus the target in an effect after that step renders. Keep summary focus tied to failed submission; changes to the errors array do not move focus themselves.
const [focusTarget, setFocusTarget] = useState<string | null>(null);
function revealAndFocus(error: FormErrorSummaryError) {
setStep(stepForTarget(error.targetId));
setFocusTarget(error.targetId);
}
useEffect(() => {
if (!focusTarget) return;
document.getElementById(focusTarget)?.focus();
setFocusTarget(null);
}, [focusTarget, step]);
<FormErrorSummary errors={errors} onErrorSelect={revealAndFocus} />;
Props
| PROP | TYPE | DEFAULT | REQUIRED |
|---|---|---|---|
errorsReadonly errors with stable unique id, readable message and targetId for the control. | array | — | yes |
titleVisible heading that names the summary section. | string | "Check these fields" | no |
onErrorSelectOptional reveal/focus handler receiving the selected error. Replaces direct target focus; reveal hidden controls before focusing them after render. | function | — | no |
className | string | — | no |
The ref targets the native section, which has tabIndex={-1} by default. Native section attributes are supported. Each instance has a unique heading association. The component supplies no aria-live; choose announcement timing in the surrounding form if needed.
Accessibility
- A visible heading names the focusable section; written messages explain each error.
- Native
type="button"actions support Tab, Enter and Space without submitting the form. - Error actions have a minimum 24px target and token focus indicators.
- Error updates do not steal focus or automatically announce the full summary.
- Each error keeps the case it was written in, matching the message under its field, so identifiers and values read exactly; the title is an uppercase label.
- The title and error text wrap for narrow layouts, and a long identifier or unbroken token breaks anywhere.
Manifest entry
<FormErrorSummary ref={summaryRef} errors={errors} onErrorSelect={revealAndFocus} />View agent manifest
{
"description": "Focusable error summary with actions that reveal or focus invalid form controls.",
"props": {
"errors": {
"type": "array",
"required": true,
"description": "Readonly errors with stable unique id, readable message and targetId for the control."
},
"title": {
"type": "string",
"default": "Check these fields",
"description": "Visible heading that names the summary section."
},
"onErrorSelect": {
"type": "function",
"description": "Optional reveal/focus handler receiving the selected error. Replaces direct target focus; reveal hidden controls before focusing them after render."
},
"className": {
"type": "string"
}
},
"composable_with": [
"Field",
"FormSection",
"Input"
],
"never_inside": [
"Button"
],
"example": "<FormErrorSummary ref={summaryRef} errors={errors} onErrorSelect={revealAndFocus} />"
}