Files
ros_control/docs/changes/020-custom-select-menus/summary.md
T
ayurishchevandClaude Opus 5.5 6b5c521461 Выпадающие списки в стиле меню действий
Все выпадающие списки (фильтры «Устройства», «Бэкапы», «Журнал», поле
«Группа» в окне устройства) оформлены как меню «⋯» (docs/changes/020):
- app.js строит меню поверх скрытого select: значение уходит с формой,
  без JavaScript работает стандартный список; выбор отправляет change —
  существующие onchange/hx-trigger не менялись;
- позиционирование — существующий placeMenu, выбранный пункт отмечен «✓»,
  клавиатура: Tab, Enter/Space, ↑/↓, Escape;
- Escape при открытом списке в окне закрывает только список.

Тесты: 24 из 24. Автотестов JS нет; ручная проверка UI пользователем на
момент коммита не подтверждена.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 12:18:32 +03:00

3.0 KiB
Raw Blame History

Итоги: 020 — выпадающие списки в стиле меню действий

Сделано

  • Все select.field (10 списков: фильтры «Устройства» ×3, «Бэкапы» ×3, «Журнал» ×3, поле «Группа» в окне устройства) выглядят как меню «⋯»: кнопка с текстом выбранного пункта и шевроном, панель .menu-panel с пунктами .mi, выбранный — «✓», включённый фильтр подсвечен.
  • app/ui/static/app.js::enhanceSelects: прогрессивное улучшение — нативный select остаётся скрытым в разметке (значение уходит с формой, без JavaScript — стандартный список). Выбор пункта ставит select.value и отправляет change — существующие onchange, hx-trigger и «+ Новая группа…» работают без изменений. Применяется при загрузке и к фрагментам HTMX (окно устройства), без дублей (data-enhanced).
  • Позиционирование — существующий placeMenu (не обрезается таблицей/окном, вверх у нижнего края), панель не уже кнопки, длинные списки прокручиваются (320px).
  • Клавиатура: Tab, Enter/Space, ↑/↓ по пунктам, Escape закрывает список и возвращает фокус на кнопку.
  • style.css: .select-btn, .select-menu — только существующие токены; шеврон через currentColor (следует теме).
  • _device_form.html: поле «Группа» в div.lbl с aria-labelledby вместо label — клик по подписи не уходит в скрытый select.

Найдено на ревью и исправлено

  • Escape при открытом списке внутри окна устройства закрывал и само окно (действие браузера по умолчанию для <dialog>) — введённые данные терялись. Исправлено: preventDefault на keydown и на cancel окна, если в момент Escape было открыто меню.

Проверено

  • pytest: 24 из 24 (серверная часть не менялась); node --check app.js — без ошибок.
  • Стенд (порт 8001) отдаёт новые app.js и style.css.

Оговорки

  • Автотестов JS в проекте нет; поведение в браузере (темы, клавиатура, окно устройства) проверяется вручную — на момент коммита пользователем не подтверждено.