Зачем на обертке модального окна навешивать id и проверять таргет клика для закрытия модалки
Что проверяют
Понимаете ли вы всплытие событий. Клик по кнопке внутри модалки всплывает до обёртки, и без проверки таргета любой клик внутри окна закрывал бы его. Следом обычно спрашивают, чем target отличается от currentTarget и как сделать модалку доступной.
Как отвечать
Сначала механика. Обработчик click висит на подложке во весь экран, а контент лежит внутри неё. Клик по контенту поднимается по дереву и тоже вызывает этот обработчик. Поэтому закрываем, только если клик пришёлся на саму подложку:
event.target: самый глубокий элемент, на котором реально произошёл клик;event.currentTarget: элемент, на котором висит обработчик.
Условие event.target === event.currentTarget решает задачу без всякого id. Сам id здесь вторичен, это просто способ найти обёртку в DOM. В компонентах он даже вредит: две модалки на странице получат одинаковый id. В React вместо него берут useRef.
Затем тонкости, которые отличают сильный ответ:
- перетаскивание: пользователь выделяет текст в поле, отпускает кнопку мыши над подложкой, и
clickприходит на общего предка, то есть на подложку. Модалка закрывается посреди ввода. Лечится проверкой, что иmousedownначался на подложке; - порталы в React: события всплывают по дереву компонентов, а не по DOM, поэтому клик внутри портала дойдёт до обработчиков родителя;
- нативный
<dialog>:showModal()даёт подложку::backdrop, закрытие поEscapeи делает остальную страницу инертной. Клик по подложке приходит сtarget, равным самомуdialog.
И доступность: role="dialog", aria-modal="true", заголовок через aria-labelledby, возврат фокуса на кнопку, которая открыла окно.
Где спотыкаются
Ставят stopPropagation() на контент. Задача решается, но ломаются другие слушатели выше по дереву: аналитика, закрытие выпадающих списков по клику снаружи.
Не знают разницы между target и currentTarget и на каждом клике ищут обёртку через getElementById, чтобы сравнить с ней.
Забывают про Escape и фокус, будто мышь это единственный способ работы с окном.