122 lines
8.6 KiB
Markdown
122 lines
8.6 KiB
Markdown
# ТРЗ — 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 360–414 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» как универсальное
|
||
решение для будущих кейсов.
|
||
|
||
Это рекомендация, конкретный набор файлов определит архитектор.
|