Problem Statement
Modal dialogs overlay content on top of the main window. Because they break the standard page hierarchy, they introduce numerous accessibility challenges:
- Keyboard focus must be locked inside the modal while open (focus trapping).
- Users expect standard close options: clicking an explicit close button, clicking the background backdrop, or pressing the
Escapekey. - Content structure must render correctly, usually breakout-mounting directly under
document.bodyto avoid parent stack overflows or z-index constraints.
We need a flexible and accessible Modal Dialog in React using Portals, supporting ESC close triggers and outside backdrop click tracking.
Requirements
Functional
- Portal Rendering: Render the modal overlay and window to a different part of the DOM tree (typically as a direct child of
document.body) using React'screatePortalAPI. - Dismiss Controls:
- Escape Key: Pressing
Escapewhile the modal is open must immediately close the modal. - Click Outside: Clicking on the overlay backdrop outside the modal dialog box boundaries must close the modal.
- Explicit Close: Provide close controls (e.g. cross icon, Cancel buttons) that dismiss the modal.
- Escape Key: Pressing
- Focus Management:
- When the modal opens, automatically shift focus to the first interactive element inside the modal.
- When the modal closes, return focus to the trigger button that opened it.
- ARIA Semantic Attributes:
- The dialog wrapper must have
role="dialog"andaria-modal="true". - Supply an
aria-labelledbypointing to the title heading ID, and an optionalaria-describedbypointing to the description element ID.
- The dialog wrapper must have
Non-Functional
- Ensure smooth entrance and backdrop opacity transitions.
- Trap focus inside the dialog so tab navigation does not cycle to parent page links.
Concepts Tested
- React Portals (
createPortal). - Custom event listener attachment (
keydown,click). - Focus trap creation and active node selection.
- ARIA dialog specifications.
