Validated Modal Form
A tested composition for validation, asynchronous submission, server errors, success announcements, and focus return inside Modal.
Use this pattern for a focused editing task that benefits from staying in context. Keep longer workflows and forms with several sections on a dedicated page.
This is composition guidance, not a registry item. Copy the example and replace saveProfile with the application request. Keep request state and server-error mapping in the application.
Interaction flow
- The trigger opens a controlled Modal and Modal moves focus into the form.
- Native constraints prevent invalid submission. The form focuses its first invalid control.
- Submission disables every control, sets
aria-busyon ModalBody, and preserves the submit button footprint. - A server field error keeps Modal open, appears beside its control, and moves focus to that control.
- Success closes Modal, announces confirmation beside the trigger, and restores focus to the trigger.
Enter taken@example.com in the preview to exercise the server-error path.
Structure
trigger Button + status region
└── Modal
├── ModalHeader
│ ├── ModalTitle
│ └── ModalSubtitle
└── Form
├── ModalBody (scroll owner and busy region)
│ ├── required name Field
│ ├── required email Field
│ └── required team Field
└── ModalActions
├── Cancel
└── Save changesModalBody owns scrolling so the title and actions remain available at narrow heights. Actions stack in DOM and keyboard order on small screens.
Validation ownership
Use native constraints for immediately knowable rules such as required values and email syntax. Pass application or server errors through Form errors, keyed to the matching Field name.
Clear a server error when its control changes so stale feedback does not survive a correction. Do not close Modal after a failed request. Keep the entered values available and focus the control that needs attention.
Submission and success
Set loading on the submit action and disable the remaining controls while the request is active. Put aria-busy on the region whose content is temporarily unavailable, not on the entire page.
After a successful request, close Modal and announce a concise confirmation through a mounted status region beside the trigger. Return focus to the trigger explicitly when closure happens after asynchronous work.
Accessibility checklist
- Keep ModalTitle and ModalSubtitle present so the dialog is named and described.
- Use visible FieldLabel elements and matching Field names for consolidated values and errors.
- Focus the first invalid control only after validation determines the submission cannot continue.
- Keep corrective error text adjacent to the field and avoid replacing the form with a generic error screen.
- Disable dismissal while submission is active so request state is not abandoned accidentally.
- Verify keyboard order, focus return, constrained-height scrolling, and the error path at desktop and mobile widths.