Доступная модалка
Вопрос
Как бы ты сделал модальное окно в React, чтобы им было удобно пользоваться и с клавиатуры, и со скринридером?
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Портал в `document.body` или нативный `<dialog>` с `showModal()`
`role="dialog"`, `aria-modal="true"`, заголовок через `aria-labelledby`
Фокус в окно при открытии, ловушка фокуса внутри, возврат фокуса на кнопку при закрытии
Закрытие по Escape и по клику на подложку, но не по клику внутри окна
Блокировка прокрутки страницы под окном
Очистка обработчиков клавиатуры при закрытии
Что могут спросить следом
- Зачем нужен портал, если есть z-index?
- Что даёт нативный dialog по сравнению с div?
- Как реализовать ловушку фокуса?
Разбор
Самый простой надёжный вариант сегодня это нативный <dialog> и метод showModal(): браузер сам ставит окно в верхний слой, делает остальную страницу инертной, закрывает по Escape. В React я держу ref на элемент и вызываю showModal и close в эффекте в зависимости от пропса open.
Если делаю на div, рендерю окно через createPortal в document.body, чтобы его не обрезали overflow и z-index родителей. Добавляю role="dialog", aria-modal="true" и связываю заголовок через aria-labelledby.
С фокусом три правила: при открытии фокус переходит в окно, Tab не выходит за его пределы, при закрытии фокус возвращается на кнопку, которая окно открыла. Закрываю по Escape и по клику на подложку, проверяя, что клик был именно по ней. Блокирую прокрутку страницы, пока окно открыто, и снимаю все обработчики при закрытии.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.