feat(web): <NavSections> shared primitive (rail + drawer variants) #1029
No reviewers
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks!1029
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "code-lead/1026"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Single source of truth for the grouped sidebar nav.
<NavSections variant="rail"|"drawer" collapsed?: boolean />renders the sameNAV_SECTIONSdata either as an icon rail (collapsed →<hr role="separator">+aria-labeltooltip wiring) or a labelled drawer. Active state is route-driven via TanStack<Link activeProps>writingaria-current="page"— highlight styling lives in CSS, no JS state.Closes #1026 — sidebar shell wiring (#nav-v2-5), tooltip layer (#nav-v2-7), and drawer integration (#nav-v2-6) ship in sibling tickets.
Test plan
bun x tsc --noEmitclean across the workspace.bun x biome check apps/web/src/components/nav-sections{,.test}.tsxclean.just paraglide-check+just i18n-string-checkpass (en + fr keys present).apps/webVitest browser-mode suite (covers section/item rendering,aria-labelledbygroup association,aria-currentflip on route change, rail-collapsed →<hr>swap, drawer never adds tooltip).libglib-2.0.so.0etc.) and the sandbox has no root; CI will run the full suite.nav-sections.tsxlines 117–160:NAV_SECTIONSis a module-level constant whoseheadingandlabelfields are eagerly populated bym.*()calls at import time. Paraglide message functions read the current locale when called — but since these calls happen once at module init, any locale change within the same SPA session leaves the nav with stale strings. Fix: replace the static constant with a factory functiongetNavSections(): NavSectionsConfig(called insideNavSectionsat render time), or makeheading/labelfields() => stringmessage refs and call them in the render. The exportedNAV_SECTIONSused by tests can stay for shape assertions if it switches to a factory; tests already check key strings so either approach is compatible.Pushed
6bd103daddressing the locale-staleness issue.NAV_SECTIONSis nowgetNavSections(): NavSectionsConfig— called inside<NavSections>so Paraglide message functions resolve at render time (not module-init). React re-runs the factory whenever the component re-renders, so an in-session locale switch picks up fresh strings. Tests switch to calling the factory for shape assertions; same data, just resolved per-call.Verified: typecheck + biome check + paraglide-check + i18n-string-check all clean. Web Vitest browser-mode suite skipped locally (sandbox is missing Playwright's
libglib-2.0.so.0— same constraint noted in the original PR test plan); CI runs the full suite.Locale-staleness fix correct —
getNavSections()factory resolves Paraglide messages at render time. CI green, all criteria met.