Files
enduro-trails/docs/work-items/ET-014/02-trz.md
claude-bot e796a6cb03
All checks were successful
CI / lint (push) Successful in 5s
CI / test (push) Successful in 10s
CI / build (push) Successful in 2s
analyst(ET): auto-commit from analyst run_id=87
2026-06-04 11:03:45 +00:00

122 lines
8.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ТРЗ — ET-014: Z-index конфликт terrain-popup vs sheet-gps-filters
**Work Item:** ET-014
**Связан с BRD:** 01-brd.md
**Тип задачи:** Bug-fix (UI / стили / DOM-stacking)
---
## 1. Анализ текущего состояния
### 1.1 DOM-структура (как есть)
- `#terrain-popup` (`src/web/index.html:43`) — `position: fixed`, `z-index: 500`
(`src/web/app.css:785-795`). Открывается по клику на кнопку «Рельеф»
(`#terrain-toggle` в `#map-controls-r`). Содержит чекбоксы слоёв,
переключатели подложки и единиц, а также кнопку-ссылку
`#public-tracks-filters-btn` с текстом «Фильтры…».
- `#sheet-gps-filters` (`src/web/index.html:478`) — класс `.bottom-sheet`,
`position: fixed`, `z-index: 400` (`src/web/app.css:183-196`). Открывается
через `togglePublicTracksFiltersSheet()` в `src/web/gps_tracks.js:737`,
который вызывает `openSheet('sheet-gps-filters')`.
- `#sheet-backdrop` (`src/web/index.html:19`) — `z-index: 390`
(`src/web/app.css:222-228`). На mobile перекрывает экран при открытом
sheet'е; на desktop скрыт (`#sheet-backdrop { display: none; }` в
media-query, `src/web/app.css:543`).
### 1.2 Стек z-index в проекте (для ориентира)
| Элемент | z-index | Файл/строка |
|-------------------|---------|-------------------------|
| `#map` | 0 | app.css:68 |
| `#no-data-warning`| 200 | app.css:410 |
| `#sheet-backdrop` | 390 | app.css:225 |
| `.bottom-sheet` | 400 | app.css:188 |
| `#map-controls-r` | 400 | app.css:129 |
| `.terrain-popup` | **500** | app.css:787 |
| `#marker-dialog` | 500 | app.css:399 |
| `#search-panel` | 600 | app.css:1101 |
| `#ruler-info` | 600 | app.css:1122 |
### 1.3 Корень проблемы
1. `togglePublicTracksFiltersSheet()` открывает sheet (z=400), но **не
закрывает** `#terrain-popup` (z=500). Popup остаётся на экране и
визуально/event-but перекрывает sheet.
2. Клик по ссылке «Фильтры…» внутри popup не триггерит
`closeTerrainOnOutside` (popup.contains(target) === true), поэтому popup
не закрывается сам.
3. Backdrop sheet'а (z=390) тоже ниже popup'а (z=500), поэтому даже на
mobile нет визуальной индикации, что popup стал «фоном».
## 2. Требования к решению
### 2.1 Функциональные (REQ-F)
| ID | Требование |
|------------|------------|
| REQ-F-01 | При открытии `#sheet-gps-filters` из «Фильтры…» панель `#terrain-popup` НЕ должна перекрывать sheet ни визуально, ни для событий ввода. |
| REQ-F-02 | Когда `#sheet-gps-filters` открыт, состояние кнопки `#terrain-toggle` (класс `.active`) должно быть консистентно с состоянием popup: если popup скрывается / закрывается на время открытия фильтров — кнопка не должна оставаться визуально «прижатой». |
| REQ-F-03 | После закрытия `#sheet-gps-filters` (через `✕`, свайп вниз, клик по backdrop на mobile, либо `closeAllSheets()`) пользователь возвращается к карте. Возврат панели слоёв — на усмотрение архитектора (см. §3 «Варианты решения»). В любом случае не должно оставаться «фантомных» оверлеев / неактивных DOM в видимой области. |
| REQ-F-04 | Решение должно работать единообразно при инициации фильтров повторно (открыли → закрыли → открыли снова). |
| REQ-F-05 | Поведение `#terrain-popup` для всех других сценариев (открыть/закрыть кнопкой, кликнуть вне popup'а, переключить чекбокс/подложку/единицы) **не должно регрессировать**. |
| REQ-F-06 | Поведение остальных bottom-sheets (`#sheet-route`, `#sheet-recon`, `#sheet-scenic`, `#sheet-link`, `#sheet-gpx`) **не должно регрессировать**. |
| REQ-F-07 | Решение должно одинаково корректно работать в светлой и тёмной теме. |
### 2.2 Нефункциональные (REQ-NF)
| ID | Требование |
|-------------|------------|
| REQ-NF-01 | Изменения локализованы во фронте (`src/web/`). Backend (`src/api/`) не затрагивается. |
| REQ-NF-02 | Нет регрессий по производительности (никаких новых тяжёлых обработчиков resize/scroll). |
| REQ-NF-03 | Если решение меняет z-index — оно не должно ломать стекинг `#marker-dialog` (z=500), `#search-panel` (z=600), `#ruler-info` (z=600). |
| REQ-NF-04 | Решение совместимо с PWA-режимом (PH-9, в работе): в standalone display и при наличии safe-area-inset. |
| REQ-NF-05 | Решение работает на mobile viewport 360414 px (Chrome Android), desktop ≥1024 px (Chrome desktop). |
## 3. Варианты решения (на усмотрение архитектора)
> Аналитик не выбирает архитектуру. Перечисляю опции, которые могут быть
> рассмотрены реализатором/архитектором:
- **Вариант A — закрывать `#terrain-popup` при открытии sheet-gps-filters.**
В `togglePublicTracksFiltersSheet()` перед `openSheet(...)` явно скрыть
popup (как делает `closeTerrainOnOutside`) и снять `.active` с
`#terrain-toggle`. Backdrop sheet'а корректно затемнит фон на mobile.
- **Вариант B — поднять z-index sheet'ов выше terrain-popup.** Например,
`.bottom-sheet { z-index: 510; }` и `#sheet-backdrop { z-index: 505; }`.
Тогда sheet физически окажется поверх popup'а. Требует проверки на не-
конфликт с marker-dialog (z=500) и не-перекрытие toolbar / search-panel.
- **Вариант C — точечно поднять z-index только `#sheet-gps-filters` и его
backdrop.** Узкий хак: `#sheet-gps-filters { z-index: 510; }`. Менее
системно, но минимальные риски регрессии для других sheet'ов.
Решение фиксируется архитектором в ADR работы (`06-adr/`).
## 4. Acceptance hooks
См. полные критерии в `03-acceptance-criteria.md`.
Краткая выжимка:
- Открытие фильтров → панель полностью видна, кликабельна (mobile и
desktop).
- Панель слоёв не перекрывает фильтры (визуально и для событий).
- Закрытие фильтров → возврат к карте без артефактов.
- Остальные оверлеи (marker-dialog, search-panel, ruler-info, остальные
sheets) — без регрессий.
## 5. Тесты
См. `04-test-plan.yaml` (функциональные тесты) и
`04b-ui-test-cases.md` (Playwright UI тест-кейсы).
## 6. Артефакты для модификации (ожидание аналитика)
- `src/web/app.css` — стили stacking-context (если выбран вариант B/C).
- `src/web/gps_tracks.js` — логика `togglePublicTracksFiltersSheet()`
(если выбран вариант A).
- Возможно `src/web/app.js` — если в `openSheet` / `closeAllSheets`
требуется хук «при открытии sheet закрыть popup» как универсальное
решение для будущих кейсов.
Это рекомендация, конкретный набор файлов определит архитектор.