feat(web): <NavSections> shared primitive (rail + drawer variants) #1026

Closed
opened 2026-05-09 18:18:26 +00:00 by claude-desktop · 0 comments
Collaborator

As a developer building both the desktop sidebar and the mobile drawer,
I want the grouped-section nav rendered by a single shared component with a variant prop,
so that desktop (rail) and mobile (drawer) stay structurally identical and any future change happens in one place.

Acceptance criteria

Component

  • apps/web/src/components/nav-sections.tsx exports <NavSections variant="rail" | "drawer" collapsed?: boolean />.
  • NAV_SECTIONS constant declares the section order: WORKAGENTS, plus a footer slot for Settings.
  • WORK: Board, Workspace, Flows.
  • AGENTS: Live, Roster, Config, Sessions, JSON.
  • Each item has { path, label, icon, testId }. Icons: lucide only (LayoutGrid, MessageSquare, GitBranch, Activity, Users, Sliders, History, Braces, Settings).

Markup

  • Top-level <nav aria-label="Primary"> (rail) or <nav aria-label="All routes"> (drawer).
  • Each section: <div role="group" aria-labelledby="navgrp-<id>"> + visible <h2> heading.
  • Each link uses TanStack <Link activeProps={{ "aria-current": "page" }}>.
  • Active state styled via [aria-current=page] selector — no JS state.
  • Icons rendered with aria-hidden; visible text or (collapsed-rail) aria-label carries the name.
  • Tap target ≥ 40 × 40 (h-10 rows).

Variant behaviour

  • variant="rail" + collapsed=true → labels hidden, group <h2> replaced by <hr role="separator">, icons + tooltips (#nav-v2-7 supplies the tooltip wiring).
  • variant="rail" + collapsed=false → labels visible, headings visible.
  • variant="drawer" → labels always visible, headings always visible, no tooltips.

Tests

  • Renders each section + items.
  • aria-current="page" flips when route changes.
  • Group → heading association via aria-labelledby.
  • Variant switch (rail vs drawer) renders correct DOM.

Out of scope

  • The sidebar shell itself (#nav-v2-5).
  • Collapse toggle / persistence / tooltips (#nav-v2-7).
  • Mobile drawer integration (#nav-v2-6).

References

  • Spec: docs/specs/nav-consolidation.md § Sidebar component, § Mobile.
**As a** developer building both the desktop sidebar and the mobile drawer, **I want** the grouped-section nav rendered by a single shared component with a `variant` prop, **so that** desktop (rail) and mobile (drawer) stay structurally identical and any future change happens in one place. ## Acceptance criteria ### Component - [ ] `apps/web/src/components/nav-sections.tsx` exports `<NavSections variant="rail" | "drawer" collapsed?: boolean />`. - [ ] `NAV_SECTIONS` constant declares the section order: `WORK` → `AGENTS`, plus a footer slot for Settings. - [ ] `WORK`: Board, Workspace, Flows. - [ ] `AGENTS`: Live, Roster, Config, Sessions, JSON. - [ ] Each item has `{ path, label, icon, testId }`. Icons: lucide only (`LayoutGrid`, `MessageSquare`, `GitBranch`, `Activity`, `Users`, `Sliders`, `History`, `Braces`, `Settings`). ### Markup - [ ] Top-level `<nav aria-label="Primary">` (rail) or `<nav aria-label="All routes">` (drawer). - [ ] Each section: `<div role="group" aria-labelledby="navgrp-<id>">` + visible `<h2>` heading. - [ ] Each link uses TanStack `<Link activeProps={{ "aria-current": "page" }}>`. - [ ] Active state styled via `[aria-current=page]` selector — no JS state. - [ ] Icons rendered with `aria-hidden`; visible text or (collapsed-rail) `aria-label` carries the name. - [ ] Tap target ≥ 40 × 40 (`h-10` rows). ### Variant behaviour - [ ] `variant="rail"` + `collapsed=true` → labels hidden, group `<h2>` replaced by `<hr role="separator">`, icons + tooltips (#nav-v2-7 supplies the tooltip wiring). - [ ] `variant="rail"` + `collapsed=false` → labels visible, headings visible. - [ ] `variant="drawer"` → labels always visible, headings always visible, no tooltips. ### Tests - [ ] Renders each section + items. - [ ] `aria-current="page"` flips when route changes. - [ ] Group → heading association via `aria-labelledby`. - [ ] Variant switch (rail vs drawer) renders correct DOM. ## Out of scope - The sidebar shell itself (#nav-v2-5). - Collapse toggle / persistence / tooltips (#nav-v2-7). - Mobile drawer integration (#nav-v2-6). ## References - Spec: `docs/specs/nav-consolidation.md` § Sidebar component, § Mobile.
claude-desktop added this to the nav-v2 milestone 2026-05-09 18:18:26 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks#1026
No description provided.