Appearance
01. Сверка исходных отчётов
Источники
| ID | Источник | Исходный verdict | Характер доказательств |
|---|---|---|---|
A | e71bb2b7…/pasted-text.txt, SHA-256 311f226e…f9cb | INCOMPLETE, затем «not release-ready» | Статический code/CSS audit; браузерные тесты тогда не запустились |
B | 83d9b3d1…/pasted-text.txt, SHA-256 15c0729c…a1f | FAIL | Chromium screenshots и ручной layout audit; есть внутренняя таблица состояний |
C | Сводный «Expert UX & UI Heuristic Audit» из текущего запроса | FAIL | Lighthouse/accessibility-tree/heuristic утверждения и три внешних screenshot |
R | Перепроверка 2026-07-18 на commit aabfa583 | FAIL, 0 P0 | System Chrome + Playwright, DOM geometry, accessibility snapshots, CSS/code inspection |
Статусы ниже:
- CONFIRMED — наблюдение воспроизведено в текущем baseline;
- PARTIAL — проблема есть, но причина, нормативная ссылка или severity в отчёте неточны;
- REJECTED — текущий код или runtime прямо опровергает заявление;
- NOT VERIFIED — риск правдоподобен, но текущего evidence недостаточно.
Нормализованный verdict
Общий FAIL валиден, потому что существуют воспроизводимые P1-дефекты на обязательном mobile viewport и в modal keyboard flow. Формулировка «критические P0» не валидна: crash, data loss или безусловный system-wide block не обнаружены. Канонический счёт ведётся по реестру, а не по сумме исходных отчётов.
Сверка layout и mobile claims
| Исходное заявление | Источник | Статус | Проверенный вывод |
|---|---|---|---|
Верхний toolbar перекрывает MapLibre navigation на 390×844 | B | CONFIRMED | На 390px площадь пересечения top row и Zoom In — 1108.4 px²; в центре Zoom находится элемент toolbar, не Zoom. Это P1 mobile occlusion. |
Правые элементы имеют left ≈455px и поэтому «вытолкнуты» из 390px viewport | C | PARTIAL | Реальный top row имеет фиксированную ширину 376.7px от x=12; на 320/360/375 его правая часть выходит за viewport, а второй ряд намеренно горизонтально scrollable. left≈455px может относиться к элементу внутри scroll strip и не доказывает page-level overflow. Корень дефекта — не зарезервированная top-right зона и слишком широкий первый ряд. |
| Core tools полностью недоступны на mobile | C | PARTIAL | Часть второго ряда доступна через горизонтальный scroll; однако перекрытые MapLibre controls действительно не получают hit target. Нельзя обобщать на все core tools. |
Changelog перекрывает Generate Loop | B | CONFIRMED | На 390×844: Changelog 32×32, intersection с Generate — 1024 px², то есть полное наложение его hit area. P1. |
Changelog перекрывает Reverse в Search drawer | B | CONFIRMED | На 390×844: intersection — 128 px². Это частичная окклюзия интерактивной области. P1, объединено с предыдущим как один positioning defect. |
100vh опасен при dynamic mobile chrome | A | CONFIRMED STATIC / NOT DEVICE-VERIFIED | MapPage.module.css использует height: 100vh; real Safari/Android Chrome не запускались. Записано как P2 risk, не как уже доказанный P1 blocker. |
| Safe-area support отсутствует | A | CONFIRMED STATIC / NOT DEVICE-VERIFIED | В apps/web/src нет safe-area-inset. Риск реален для notch/home-indicator, но физическое устройство и landscape Safari не проверялись. P2. |
Нужно обязательно перенести map tools в Bottom Bar <768px | C | REJECTED AS PRESCRIPTION | Это один из вариантов дизайна, но evidence доказывает необходимость свободной top-right зоны, а не конкретную архитектуру. Сначала нужен минимальный responsive contract и regression test. |
Сверка accessibility и keyboard claims
| Исходное заявление | Источник | Статус | Проверенный вывод |
|---|---|---|---|
SaveModal не имеет role="dialog", aria-modal и имени | A | REJECTED | Текущая SaveModal имеет role="dialog", aria-modal="true", aria-labelledby="save-modal-title"; accessibility snapshot показывает dialog "Save Track". |
SaveModal не удерживает фокус | A | CONFIRMED | Начальный фокус корректно попадает в #track-name, но после 14 Tab фокус выходит из диалога. Background остаётся keyboard reachable. P1. |
| Modal focus trap «correctly active» | B | REJECTED | Прямой tab-cycle опровергает заявление. Скриншот или наличие initial focus не доказывает containment. |
| Escape закрывает все поверхности одновременно | A | CONFIRMED, SEVERITY CORRECTED | При Route Builder + Save открытых один Escape закрывает и dialog, и underlying panel. Это P1 layer-management defect, а не P0. |
| Gradient visible label не входит в accessible name | C | CONFIRMED | Snapshot: button accessible name Color route by slope percentage, visible text Gradient. Это нарушение label-in-name (WCAG 2.5.3) и P2. |
| Fieldset Surface/Gradient не имеет group label | C | REJECTED | В текущем коде есть aria-label="Route color mode" и visually hidden <legend>Route color mode</legend>. Snapshot показывает group "Route color mode". Дублирование можно упростить, но missing label нет. |
Changelog — безымянная icon button, потому что нет aria-label | B | REJECTED AS FAILURE | У кнопки есть title="What's New (Changelog)"; в текущем accessibility tree это имя кнопки. Явный aria-label может повысить переносимость, но безымянной кнопка сейчас не является. |
| Keyboard focus идёт через MapLibre до primary tools | C | CONFIRMED HEURISTIC | Первые элементы: Map, Zoom In, Zoom Out, compass, attribution toggle, MapLibre link, затем Routing profile. Trap нет; порядок может быть утомительным. Это P2, пока нет доказанного block. |
Контраст Logout — 2.39:1 | C | CONFIRMED | Независимый расчёт для #939ab7 на #585b70 дал 2.40:1; ниже 4.5:1 для обычного текста. P2; если это icon-only control, отдельно проверяется non-text contrast/focus state. |
| Общий contrast audit PASS | B | REJECTED | Logout sample уже опровергает blanket PASS. Полный palette sweep не выполнен, поэтому нельзя ни объявить весь UI PASS, ни распространить один failure на весь UI. |
Все кнопки 32×32 нарушают WCAG | A/C | REJECTED | WCAG 2.2 AA SC 2.5.8 требует минимум 24×24 либо spacing exception. 32×32 проходит размер AA; 44×44 — продуктовая coarse-pointer цель и WCAG 2.5.5 AAA. |
Swatches 16×16 слишком малы | A/C | CONFIRMED / NARROWED | При gap 4px соседние центры примерно в 20px, поэтому AA spacing exception для 24px не очевидна и должна считаться failure до исправления. Также не достигается продуктовая цель 44px. |
Slope legend 24×24 нарушает minimum | A | REJECTED NORMATIVELY | Ровно 24×24 соответствует WCAG 2.2 AA minimum, но ниже продуктового comfort target. P3 ergonomic. |
Route point hint 28px и маленькие reset buttons — нормативный failure | A | PARTIAL | Выше AA minimum по одной оси не всегда достаточно; нужны точные обе оси и spacing. Пока это P3 measurement needed, не автоматический blocker. |
Сверка design-system claims
| Исходное заявление | Источник | Статус | Проверенный вывод |
|---|---|---|---|
MapPage.tsx содержит hardcoded theme colors | A/B | CONFIRMED | Top-right и Changelog controls используют raw hex. Это создаёт theme drift и должно быть перенесено на semantic tokens. P2. |
SurfaceBreakdown literals автоматически являются дефектом | B | PARTIAL | Литералы подтверждены, но surface/data-visualization colors могут требовать стабильной палитры. Нужна явная semantic/data token policy и contrast check, а не механическая замена. |
Все hardcoded radii, включая 50%, нужно заменить токенами | C | REJECTED AS BLANKET RULE | 50% для круга — семантическая геометрия, а не token drift. Проверяем только повторяющиеся component radii, которые должны соответствовать design scale. |
Raw z-index 950/1000/1100 и var(--z-toast) на modal опасны | A/C | CONFIRMED STATIC | Значения существуют и нарушают текущую scale. Но runtime collision не доказан для каждого случая; ExportModal на toast layer — наиболее конкретный конфликт. Общая cleanup — P2, не несколько независимых P1. |
Любой внутренний z-index: 10/50 должен быть глобальным token | A | REJECTED AS BLANKET RULE | Локальный stacking context может корректно использовать 1/2/10. Token нужен для межкомпонентных overlay layers, а не для каждого internal layer. |
Breakpoints 767/768/560/640/680 обязательно ошибка | A | PARTIAL | Несогласованность подтверждена; разные content breakpoints могут быть намеренными. Требуется инвентаризация и convention, но не массовая замена. P3. |
BottomBar bottom: 36px сам по себе ломает landscape | A | NOT VERIFIED | Magic number подтверждён; clipping на реальном landscape viewport не воспроизведён. Рассматривать вместе с dvh/safe-area geometry. |
mobileDrawerOverlay rgba(...) обязан использовать token | A | CONFIRMED LOW-SEVERITY | Literal есть; исправлять при theme/token pass после проверки alpha в обеих темах. P3. |
| Только одна animation respects reduced motion | A | PARTIAL | Несколько perpetual/entry animations без guard подтверждены. Точное число меняется с кодом; важен сценарий, а не счёт grep. pulseSave и другие infinite animations требуют явного reduce path. P2. |
Сверка test и evidence claims
| Исходное заявление | Источник | Статус | Проверенный вывод |
|---|---|---|---|
| E2E не запускаются из-за stale browser | A | HISTORICALLY TRUE, NOW RESOLVED | С PLAYWRIGHT_BROWSER_CHANNEL=chrome целевые suites запускаются в system Chrome. Это не продуктовый дефект. |
| Layout/toolbar baseline tests зелёные | R | CONFIRMED | map-layout, responsive-map-controls, toolbar-fsm: 3 passed. Они не содержат assertions на найденные cross-surface collisions. |
| Visual regression PASS | B | REJECTED AS TERMINOLOGY | visual-regression-audit.spec.ts делает page.screenshot(), но не использует toHaveScreenshot() или image diff. Успешный run означает capture PASS, не visual-regression PASS. |
Ledger 23/24 PASS | B | INTERNALLY INCONSISTENT | В собственной таблице отчёта присутствуют 8 FAIL из 24 строк; арифметически это 16/24 PASS, если считать строки буквально. Канонический ledger пересобран отдельно. |
| Focus/contrast/accessible-name automated PASS | B | UNSUPPORTED | В зависимостях нет axe; отчёт не даёт reproducible command или raw result. Ручные probes нашли противоречия. |
waypoint-interactions strict-mode locator flaky | B | NOT RE-RUN IN THIS BASELINE | Claim сохранён как test-debt candidate, но не входит в подтверждённые blockers до отдельного воспроизведения. |
Что переносим в backlog
В backlog переходят только нормализованные записи с ID из следующего документа. Исходный severity, предлагаемый fix и ссылка на стандарт не переносятся автоматически. Особенно важно:
- не строить mobile bottom bar только потому, что так предложено в отчёте C;
- не добавлять второй accessible label там, где имя уже существует, прежде чем исправить реальную label-in-name проблему;
- не проводить массовую замену всех z-index/radius/color literals;
- не объявлять полное соответствие a11y после одного Lighthouse или screenshot run.