From c20e2bf14bff1f919780f56f8f49329730ed667c Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Thu, 22 Oct 2026 08:47:43 +0400 Subject: [PATCH] =?UTF-8?q?=D0=A1=D0=BF=D0=B5=D0=BA=D0=B0=20=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BB=D0=B0=D0=BD:=20=D0=B1=D0=BE=D0=BA=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D1=8F=20=D0=BF=D0=B0=D0=BD=D0=B5=D0=BB=D1=8C,=20=D0=B4?= =?UTF-8?q?=D0=BE=D1=81=D0=BA=D0=B0=20=D0=B1=D0=B5=D0=B7=20=D1=87=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D0=B4=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=D0=B4?= =?UTF-8?q?=D0=BE=D1=80=D0=BE=D0=B6=D0=B5=D0=BA=20(#69)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- docs/superpowers/plans/2026-10-22-sidebar.md | 65 +++++ openspec/changes/sidebar/.openspec.yaml | 2 + openspec/changes/sidebar/design.md | 85 ++++++ openspec/changes/sidebar/proposal.md | 24 ++ .../changes/sidebar/specs/web-app/spec.md | 254 ++++++++++++++++++ 5 files changed, 430 insertions(+) create mode 100644 docs/superpowers/plans/2026-10-22-sidebar.md create mode 100644 openspec/changes/sidebar/.openspec.yaml create mode 100644 openspec/changes/sidebar/design.md create mode 100644 openspec/changes/sidebar/proposal.md create mode 100644 openspec/changes/sidebar/specs/web-app/spec.md diff --git a/docs/superpowers/plans/2026-10-22-sidebar.md b/docs/superpowers/plans/2026-10-22-sidebar.md new file mode 100644 index 0000000..f5f7113 --- /dev/null +++ b/docs/superpowers/plans/2026-10-22-sidebar.md @@ -0,0 +1,65 @@ +# Боковая панель и доска без чередования — план + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** заменить верхнюю панель приложения закреплённой боковой (со свёрткой и выезжающим вариантом на узком экране), убрать чередование дорожек доски и показать просрочку на карточке доски. + +**Architecture:** `Layout` рисует grid `.shell` из `Sidebar` и `main.page`; прокрутка остаётся у окна. `Sidebar` собирает существующие `ProjectPicker`, `DataStatus`, `ThemeSwitch`, `Menu`; режим (развёрнута / свёрнута / узкий экран) — локальное состояние + `localStorage` + `matchMedia`. Доска: CSS и проп `today` у `Card`. + +**Tech Stack:** React 19 + TS, Vitest + Testing Library, Playwright. + +**Spec:** `openspec/changes/sidebar/` (proposal, design, specs/web-app/spec.md) + +## Global Constraints + +- Литералы цвета — только в `web/src/styles/tokens.css` (тест `tokens.test.ts`). +- Ключ свёртки `jira-hub-sidebar`, значение `collapsed`; без записи — развёрнута; доступ к `localStorage` в `try/catch`. +- Ширины: развёрнутая 240 px, свёрнутая 64 px; узкий экран — `(max-width: 639px)`, строка 56 px, выезжающая панель `min(300px, 85vw)`. +- Подписи: «Хаб Jira», «Свернуть панель», «Развернуть панель», «Меню», «Разделы», «Доска связей», «Задачи», «Обновить из Jira», «просрочено». +- Модель доски, golden-эталоны, API, ключи `graph-*` не меняются. + +## Review Focus + +- Прокрутка доски у окна: восстановление прокрутки, липкая шапка, полоса дат, ящик «Проблемы», `.hscroll` — после смены каркаса (e2e `board.spec` сценарии прокрутки). +- Окно карточки и окна диалогов поверх панели (z-index), фокус возвращается после закрытия. +- Узкий экран: выезжающая панель не оставляет горизонтальной прокрутки и закрывается при переходе по ссылке. +- Свёрнутая панель: «Обновить из Jira» показывает ход пакета (значок крутится, текст события в `title`/`role=status`). +- Просрочка: граница — срок сегодня не просрочен; закрытая задача не просрочена. + +--- + +### Task 1: Доска — без чередования, просрочка на карточке + +**Files:** `web/src/board/board.css`, `web/src/styles/tokens.css`, `web/src/styles/tokens.test.ts`, `web/src/board/components/Card.tsx`, `web/src/board/components/BoardCanvas.tsx` (передача `today`), `web/src/board/BoardPage.tsx`, `web/src/styles/base.css` (`.visually-hidden`, если нет), тест `web/src/board/components/Card.test.tsx`. + +- [ ] Тест `Card`: `today="2026-10-22"`, `due="2026-10-20"`, не закрыта → `.due.late`, `title="просрочено"`, текст «просрочено» в DOM; `closed` → без `late`; `due="2026-10-22"` → без `late`. +- [ ] Тест токенов: в `tokens.css` нет `--lane-alt`. +- [ ] Реализация (design 9, 10); `cardPropsEqual` сравнивает `today`. +- [ ] `npx vitest run` зелёный, коммит. + +### Task 2: Боковая панель (широкий экран) + +**Files:** create `web/src/shell/Sidebar.tsx`, `web/src/shell/sidebarPref.ts`, `web/src/shell/Sidebar.test.tsx`; modify `Layout.tsx`, `DataStatus.tsx` (проп `compact`), `shell.css`, `projects/projects.css`, `ui/Menu.tsx` (`up`), `ui/ui.css`, `ui/icons.tsx`; delete `AppBar.tsx`, `AppBar.test.tsx` (перенести его проверки в `Sidebar.test.tsx`). + +**Interfaces:** `readSidebar(): boolean` (true — свёрнута), `saveSidebar(collapsed: boolean): void`; `Sidebar({ section, project }: { section: Section | null; project: string | null })`; `Section` переезжает в `Sidebar.tsx`. + +- [ ] Тесты: ссылки «Доска связей»/«Задачи» с `aria-current`; «Свернуть панель» → `localStorage['jira-hub-sidebar']==='collapsed'`, ссылки с `aria-label`, повторный рендер — свёрнута; «Сменить токен» очищает токен; в свёрнутой — кнопка «Обновить из Jira» и `role=status`. +- [ ] Реализация (design 1–3, 6–8). +- [ ] `npx vitest run` и `npm run lint` зелёные, коммит. + +### Task 3: Узкий экран + +**Files:** `Sidebar.tsx`, `Layout.tsx`, `shell.css`, `board/board.css` (`--topbar-h` у `.drawer`), `Sidebar.test.tsx`. + +- [ ] Тесты (matchMedia замокан на узкий): видна кнопка «Меню», панели нет; «Меню» → панель открыта (`aria-expanded=true`), фокус на первой ссылке; Escape → закрыта, фокус на «Меню»; щелчок по разделу → закрыта. +- [ ] Реализация (design 4, 5). +- [ ] vitest зелёный, коммит. + +### Task 4: e2e, снимки, документация + +**Files:** `web/e2e/*.spec.ts`, `web/e2e/hub.ts`, `web/e2e/screens.spec.ts`, `ARCHITECTURE.md`. + +- [ ] Поправить селекторы `.appbar`/сегментов на панель; новый e2e: после прокрутки доски вниз ссылка «Задачи» в панели видна в окне (`toBeInViewport`); свёртка переживает перезагрузку; на 390 «Меню» → «Задачи» → список, `scrollWidth <= innerWidth`. +- [ ] `screens.spec`: добавить снимки `board-collapsed` (1920) и `menu` (390). +- [ ] ARCHITECTURE.md: оболочка — боковая панель. +- [ ] `make check`, `npm run e2e`, `SCREENS=1 npx playwright test e2e/screens.spec.ts` зелёные; коммит, push. diff --git a/openspec/changes/sidebar/.openspec.yaml b/openspec/changes/sidebar/.openspec.yaml new file mode 100644 index 0000000..7cc41bb --- /dev/null +++ b/openspec/changes/sidebar/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-10-22 diff --git a/openspec/changes/sidebar/design.md b/openspec/changes/sidebar/design.md new file mode 100644 index 0000000..4e226e1 --- /dev/null +++ b/openspec/changes/sidebar/design.md @@ -0,0 +1,85 @@ +## Context + +`main` 7911dc7 (после #66/#67). Оболочка: `web/src/shell/Layout.tsx` рисует `AppBar` (`shell/AppBar.tsx`: название, +`ProjectPicker`, `Segmented` разделов со ссылками, `DataStatus`, `ThemeSwitch`, `Menu` «Ещё» со «Сменить токен») и +`
`. Прокрутка страниц — у окна (`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` рисует `
` с `Sidebar` и `
`. `.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` на всю ширину; `