Выпадающий список
Условие
Свой select. Требования: · кнопка <button class="trigger"> показывает выбранное значение или «Выберите»; · список - <ul class="menu"> с <li class="option" data-value={value}>; · список открывается и закрывается кликом по кнопке; · выбор пункта закрывает список и вызывает onChange(value); · клик вне компонента закрывает список; · Escape закрывает; · у кнопки aria-expanded, у выбранного пункта aria-selected.
Что проверяют тесты
закрыт по умолчанию
открывается и закрывается кнопкой
выбор закрывает и сообщает наружу
клик снаружи закрывает
клик внутри не закрывает
Escape закрывает
слушатели снимаются при закрытии
Как подойти
Три способа закрытия и одна общая ловушка: клик по самой кнопке дойдёт и до document-слушателя, и до onClick кнопки - получится открыть-и-сразу-закрыть. Спасает проверка contains: кнопка внутри root, поэтому внешний обработчик её игнорирует. mousedown вместо click - потому что к моменту click кликнутый пункт уже может быть размонтирован, и contains вернёт false. Что назвать вслух: навигация стрелками и Home/End, набор первых букв, role=listbox с aria-activedescendant, позиционирование в портале.
Подсказки: 3
- Определение «клик снаружи» - это !root.contains(e.target).
- Слушатель вешается только пока список открыт - и снимается в очистке эффекта.
- mousedown, а не click: пункт может быть удалён из дерева до всплытия click.
Решите в тренажёре
Редактор с автотестами прямо в браузере. Можно решить спокойно, вслух или под таймером, как на собесе.