An accessible modal uses role='dialog' aria-modal='true' with an accessible name, renders in a portal, traps Tab focus inside while open, moves focus in on open and restores it to the trigger on close, closes on Escape and overlay click, and makes background content inert. The native <dialog> element gives most of this for free.
Use semantic HTML first (`button`, `label`, `nav`); reach for ARIA only when no semantic element fits. Ensure keyboard operability, visible focus, sufficient contrast, and screen-reader-friendly names. Test with VoiceOver/NVDA and a keyboard.
Toasts appear without user action, so screen readers won't notice them unless you use an ARIA live region. Put a permanent live-region container in the DOM (role='status'/aria-live='polite' for info, role='alert'/aria-live='assertive' for errors) and inject toast text into it. Don't move focus to the toast, and keep it on screen long enough to be read.
Build on semantic HTML so the screen reader gets role/name/state for free, ensure full keyboard operability, give every control an accessible name, manage focus on dynamic changes, announce async updates with aria-live, and verify by actually navigating with VoiceOver/NVDA — not just running axe.
WCAG is the W3C standard organized around four principles — Perceivable, Operable, Understandable, Robust (POUR) — with three conformance levels (A, AA, AAA). AA is the practical legal/industry target. You implement it with semantic HTML first, ARIA only to fill gaps, keyboard operability, sufficient contrast, visible focus, accessible names, and testing with axe + a real screen reader.