Ревью: модальное окно
Вопрос
Перед тобой код на ревью. Скажи вслух, что здесь не так - по убыванию важности.
Читай вслух, как на ревью: сначала что делает код, потом что сломано.
function Modal({ open, onClose, children }) {
if (!open) return null;
return (
<div className="overlay" onClick={onClose}>
<div className="modal">
{children}
<span className="close" onClick={onClose}>×</span>
</div>
</div>
);
}
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
клик внутри модалки всплывает до оверлея и закрывает её
нет закрытия по Escape
нет ловушки фокуса - Tab уходит на элементы под модалкой
фокус не переносится в модалку и не возвращается при закрытии
span вместо button: нет фокуса, нет Enter, нет роли
нет role=dialog, aria-modal и заголовка, и фон не скрыт от скринридера
Что могут спросить следом
- Как реализовать ловушку фокуса?
- Почему модалку рендерят через портал?
Разбор
Функциональная ошибка первая: обработчик на оверлее ловит всплывшее событие
из содержимого - клик по любому полю внутри закроет окно. Нужна проверка
e.target === e.currentTarget.
Вторая: нет закрытия по Escape - базовое ожидание от модального окна.
Доступность. Фокус остаётся на странице под окном: Tab уводит на элементы, которые визуально закрыты. Нужны перенос фокуса внутрь при открытии, ловушка фокуса внутри и возврат на элемент-инициатор при закрытии.
span с обработчиком не фокусируется и не реагирует на Enter - это <button type="button" aria-label="Закрыть">.
И разметка: role="dialog", aria-modal="true", связь с заголовком через
aria-labelledby, а фон стоит скрыть от скринридера (inert или aria-hidden).
Практический вывод для ревью: модалки лучше не писать руками - брать реализацию, где это уже сделано.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.