Overlays and the focus trap
Overlay UI — modals, confirm dialogs, toasts — looks simple: show a <div>, hide a <div>. But for accessibility (a11y) it's one of the trickiest spots, and here lies a real bug we fixed ourselves.
The bug. You open a modal. You press Tab. Focus jumps to the buttons behind the modal — on the page that "should be unreachable". With a mouse you'd never see it. But a keyboard or screen-reader user is now lost: they're "walking" through an invisible background with no idea where they are.
This isn't cosmetics. It's a WCAG 2.1 requirement (2.4.3 Focus Order, 2.1.2 No Keyboard Trap), and real apps get audited on it. Every dialog must:
- Move focus in when it opens.
- Trap focus inside while it's open (
Tabon the last element wraps to the first;Shift+Tabon the first wraps to the last). - Restore focus to whatever opened the dialog when it closes.
Three more accessibility pieces we'll add:
- Hide the background from screen readers (
aria-hiddenon the other elements) — otherwise a screen reader still "sees" and reads the page behind the modal. - Announce changes (
aria-live) — the things a sighted user sees but a blind one would miss ("12 pictures loaded"). - Keyboard for the star rating. Our stars were mouse-only — unreachable by arrow keys. A genuine accessibility failure; we fix it with
makeRadioGroup.
Notice the theme: modals, confirms and toasts all rest on the same thing — an overlay + focus management + Esc/backdrop to close. Understand it once, apply it to all.