Modal
How the Modal works with a keyboard and assistive tech, and where it stands against WCAG 2.2 AA.
The Modal is a native <dialog> opened with showModal(). The browser makes everything behind it inert, moves focus inside and returns it to the opener on close, which is most of the WAI-ARIA dialog pattern for free. The component names the dialog by its title, describes it by its copy, and closes on Escape, the close button or a click on the overlay.
Keyboard#
Moves to the next control inside the modal. The page behind is inert, so focus never lands there.
Moves to the previous control inside the modal.
Closes the modal. Focus returns to the control that opened it.
Activates the focused button.
Activates the focused button, or ticks the footer checkbox or toggle.
Semantics#
<dialog>Opened with showModal(), which gives it the dialog role, makes it modal and the rest of the page inert.
Openaria-labelledbyPoints at the title (an <h2>), so the dialog is announced by name when it opens.
Alwaysaria-describedbyPoints at the status copy or the header description.
Has a descriptionrole="alertdialog"For a status modal that asks people to confirm something irreversible, set it on the <dialog> so it is announced as urgent.
Destructive confirmation<button aria-label="Close">The 24px close button in the header. A Status Modal has none; Escape and Cancel close it.
Header closearia-hidden="true"The icon is decorative. The title says Error, Warning or Success in words.
Status iconColour contrast#
Every variant and state has to meet WCAG 2.2 Level AA. Measure the colours as they land on screen: a translucent hover or press wash over whatever sits behind it.
Title and copy · Always
The title is #2a2a2a on white (14.35:1); the description and body #6d6d6d (5.17:1).
WCAG 1.4.3 Contrast (Minimum) ↗Footer buttons · Rest, Hover
12px Cancel and Continue labels against their fills. Continue is white on brand blue; Cancel is #6d6d6d on white with a #e1e1e1 edge.
WCAG 1.4.3 Contrast (Minimum) ↗Status icon · Status Modal
The glyph on its tint: Error 3.60:1, Warning 2.02:1, Success 3.37:1, Information 4.81:1. Warning falls short, which is acceptable only because the title states the status.
WCAG 1.4.11 Non-text Contrast ↗WCAG 1.4.1 Use of Color ↗Focus indicator · Focus visible
A 2px #1a6ef8 ring off a 2px white gap on every control (4.54:1). The modal is centred and capped to the screen, so the focused control is never hidden behind it.
WCAG 1.4.11 Non-text Contrast ↗WCAG 2.4.13 Focus Appearance ↗WCAG 2.4.11 Focus Not Obscured ↗Keyboard containment · Open
Focus stays inside while the modal is open, and Escape always closes it. Tab can still reach the browser's own controls, which is expected.
WCAG 2.1.2 No Keyboard Trap ↗WCAG 2.4.3 Focus Order ↗Measured contrast#
Footer labels and the header's close glyph against their fills, at rest and on hover, on the modal's white surface. All 8 pairs reach their minimum.
Motion#
- The surface rises 6px and fades in over 200ms, and the overlay fades over 160ms, only when motion is allowed.
- Under prefers-reduced-motion it appears at once. The overlay's blur is static.
Checklist#
Every modal has a visible title wired to aria-labelledby. A modal with no title needs an aria-label.
For a destructive confirmation, put initial focus on the least destructive control (Cancel), using autofocus.
Overlay clicks close the modal. For a form that would lose typed data, confirm before closing, or turn that off.
The header close button is 24px, exactly the target minimum. Footer buttons are 40px.
Keep the body short. Anything long or worth linking to belongs on a page.
The Warning status icon is below 3:1 on its tint; the title must always say what happened.
