Andrey Epifancev 3f75eb5909 Архив OpenSpec: sidebar (#69)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 10:01:08 +04:00

13 KiB
Raw Blame History

Context

main 7911dc7 (после #66/#67). Оболочка: web/src/shell/Layout.tsx рисует AppBar (shell/AppBar.tsx: название, ProjectPicker, Segmented разделов со ссылками, DataStatus, ThemeSwitch, Menu «Ещё» со «Сменить токен») и <main className="page …">. Прокрутка страниц — у окна (window.scrollY): на этом держатся восстановление прокрутки доски (BoardCanvas), липкая шапка доски (.sticky, top: 0, высота — в --head-h), липкая полоса дат, ящик «Проблемы» и полоса горизонтальной прокрутки .hscroll (bottom: 0). Верхняя панель не липкая (решение 15 #65), поэтому уезжает.

Доска: .lane:nth-child(even of .lane){background:var(--lane-alt)}; колонки дат .dcol (.past — 5% --p-crit, .today — 7% действия) рисуются в DOM до дорожек, поэтому непрозрачный фон чётной дорожки закрывает их подсветку. Карточка (board/components/Card.tsx) показывает «до {дата}» без признака просрочки; признак есть только в карточке задачи (issues/card.ts isOverdue, бейдж «просрочено») и в списке (красная дата).

Goals / Non-Goals

Goals: навигация и «Обновить из Jira» всегда на экране; доска шире не теряет (свёртка); просрочка видна на доске.

Non-Goals: см. proposal.

Decisions

  1. Каркас. Layout рисует <div class="shell"> с Sidebar и <main class="page …">. .shell — grid grid-template-columns: var(--sidebar-w) minmax(0, 1fr); панель position: sticky; top: 0; height: 100dvh; overflow-y: auto. Прокрутка остаётся у окна — восстановление прокрутки, липкие шапка доски, полоса дат, ящик и .hscroll работают без изменений. Ширина: развёрнутая 240 px, свёрнутая 64 px (--sidebar-w).
  2. Состав развёрнутой панели (сверху вниз): строка «Хаб Jira» + кнопка-иконка «Свернуть панель» (aria-expanded); ProjectPicker на всю ширину; <nav aria-label="Разделы"> — ссылки «Доска связей» и «Задачи» со значками, высота 40 px, текущая — фон --color-bg-selected, текст действия, aria-current="page"; разделитель с автоматическим отступом; блок данных DataStatus в колонку (агент, «данные на …», кнопка «Обновить из Jira» на всю ширину, строка события под кнопкой с переносом — абсолютное позиционирование события из R-7 #65 больше не нужно); строка: ThemeSwitch слева, Menu «Ещё» справа, меню открывается вверх.
  3. Свёрнутая панель. Только значки: кнопка «Развернуть панель», метка текущего проекта мелким текстом (до 6 символов, полный текст в title; щелчок разворачивает панель), значки разделов (aria-label = название раздела, title), «Обновить из Jira» — IconButton с крутящимся значком при пакете и точкой агента в углу, событие пакета — в title и в скрытом role="status", тема, меню. Ключ localStorage jira-hub-sidebar: collapsed — свёрнута, иначе развёрнута; чтение и запись — в try/catch.
  4. Узкий экран (<640 px). Панели в потоке нет: сверху липкая строка 56 px — кнопка «Меню» (IconMenu, aria-expanded), «Хаб Jira», справа IconButton «Обновить из Jira». «Меню» открывает ту же развёрнутую панель поверх страницы (фиксирована слева, ширина min(300px, 85vw), подложка --color-overlay); закрывается выбором раздела, Escape, щелчком по подложке; фокус при открытии — на первую ссылку раздела, при закрытии — на «Меню». Свёртка на узком экране не действует. Режим определяется matchMedia("(max-width: 639px)") с подпиской на смену.
  5. Шапка доски остаётся липкой с top: 0 (теперь это верх окна); правило @media (max-width:640px){.sticky{position:static}} не трогаем, только top у .sticky, .dates-bar и .drawer на узком экране сдвигается на высоту строки 56 px через --topbar-h (0 на широких).
  6. Меню вверх. Menu получает проп up?: boolean → класс dd--up (.dd--up > .dd-menu { top: auto; bottom: calc(100% + 4px) }).
  7. Иконки. Новые в ui/icons.tsx: IconBoard (граф из трёх узлов), IconList (строки), IconMenu (три линии), IconSidebar (прямоугольник с полосой слева).
  8. AppBar удаляется, Segmented больше не нужен оболочке (остаётся в ui для списка задач). .appbar … в shell.css и projects.css заменяются стилями .sidebar.
  9. Дорожки без чередования. Правило .lane:nth-child(even of .lane) и токен --lane-alt удаляются в обеих темах; развёрнутые дорожки прозрачны (фон — поверхность .wrap), разделитель — верхняя граница; свёрнутая дорожка остаётся на --color-bg-track.
  10. Просрочка на карточке доски. Card получает проп today: string (ISO, из BoardPage, где он уже есть для computeVisible) и считает late = !closed && !!n.due && n.due < today; у .due класс late — цвет --color-status-error, title="просрочено", скрытый текст «, просрочено» (.visually-hidden). Карточка в слое измерения тоже получает today, размер не меняется (скрытый текст вне потока). Сравнение в cardPropsEqual дополняется today. Модель доски и эталоны не меняются.
  11. Тесты. Vitest: Sidebar (разделы и aria-current, свёртка и ключ jira-hub-sidebar, «Сменить токен», узкий режим: «Меню» открывает и Escape закрывает, выбор раздела закрывает), Card (просрочка: незакрытая с прошедшим сроком — late, закрытая и будущая — нет), тест токенов (нет --lane-alt). Playwright: существующие сценарии с новыми селекторами; новый — панель видна после прокрутки доски вниз и свёртка переживает перезагрузку; screens.spec — снимки свёрнутой панели и открытого меню на 390.

Risks / Trade-offs

  • [Панель 240 px сужает доску на ноутбуке] → свёртка в 64 px, выбор запоминается.
  • [Две копии меню на узком экране (строка и панель)] → нет: на узком экране панель одна, она же выезжает; в строке только «Меню» и «Обновить из Jira».
  • [e2e и юнит-тесты, завязанные на .appbar] → правятся в той же задаче, что и разметка.

Decisions made without discussion

Владелец 22.10.2026: «в графе связей идёт чередование строк по цвету. оно мешает. его или сделать менее заметным или убрать вообще, тк не видно просроченные задачи, и закрепить хэдер, а лучше сделать его сайдбаром». Ранее (#65) отдал UX на усмотрение агента. Всё ниже — решения агента.

# Дата Решение Обоснование Цена ошибки
1 22.10.2026 Боковая панель, а не липкая верхняя (решения 1–2) владелец предпочёл «лучше сайдбар»; вертикальный список разделов растёт без переноса строк средняя: вернуть верхнюю панель — новая вёрстка оболочки
2 22.10.2026 Чередование убрано совсем, не ослаблено (решение 9) любой непрозрачный фон дорожки снова закроет колонки дат; разделителя-линии достаточно низкая: вернуть правило и токен
3 22.10.2026 Просрочка на карточке доски цветом ошибки + «просрочено» в подсказке (решение 10) «не видно просроченные» — вне режима «по датам» просрочку на доске не было видно вовсе низкая: класс и проп
4 22.10.2026 Свёртка панели в полосу 64 px с запоминанием (решение 3) доске нужна ширина; раз в спринт граф — тогда удобно свернуть низкая
5 22.10.2026 На узком экране — строка с «Меню» и выезжающая панель (решение 4) закреплённая панель 4–5 строк (M-12 #65) съела бы экран низкая: узкий экран — только «без поломок»
6 22.10.2026 Развёрнута по умолчанию, ширина 240 px на 1920 место есть; название проекта видно целиком низкая
7 22.10.2026 R-1: панель без overflow-y:auto (вопреки решению 1) прокрутка панели обрезала бы меню «Ещё» свёрнутой панели, выходящее за 64 px низкая: на окне ниже ~470 px низ панели обрезан (M-5)
8 22.10.2026 R-2: в выезжающей панели «Закрыть меню» вместо «Свернуть панель» свёртка внутри выезжающей панели бессмысленна (решение 4) нет
9 22.10.2026 R-3: e2e M-3 переходит по разделам обычным щелчком, не dispatchEvent панель закреплена, щелчок больше не прокручивает доску; тест заодно проверяет закрепление нет
10 22.10.2026 R-4 (C-1): .shell>.page{width:100%} и .page — контейнер (container: page/inline-size); пороги раскладки страниц (фильтры списка, прокрутка таблицы, колонка ящика «Проблемы») — запросами к контейнеру с порогами «прежний порог окна минус поля страницы 48 px» рядом панель 240/64 px: ширина страницы больше не равна ширине окна, и пороги по окну давали таблицу шире страницы низкая: пороги — числа в CSS
11 22.10.2026 R-5 (I-1): на узком экране событие пакета — строкой под закреплённой строкой (aria-hidden, озвучивает role=status кнопки) на телефоне подсказок нет, результат «Обновить из Jira» был не виден низкая: строка занимает 1–2 строки по высоте, пока есть событие