feat(frontend): Spectrum UX port — Tabs + AlertBanner + BackLink + compact tables (sprint 11) #13

Merged
knacky merged 11 commits from sprint/11-spectrum-ux into main 2026-06-22 08:25:38 +00:00

11 Commits

Author SHA1 Message Date
Knacky
2c7fcec7cd fix(frontend): add text- prefix to caption-bold and caption-md @apply (sprint 11 build fix)
caption-bold and caption-md are fontSize tokens — Tailwind generates
text-caption-bold / text-caption-md utilities, not bare-name utilities.
Missing text- prefix caused @apply resolution failure in vite build
(PostCSS step), while vitest passed because it does not resolve @apply.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 22:38:01 +02:00
Knacky
11ce3cfb86 fix(frontend): code-review polish — replaceState, arrow-key nav, TabId, comment
Fix 4: useHashTab navigate() uses history.replaceState instead of
window.location.hash assignment — no spurious history entries, no
anchor-jump scroll side-effect.
Fix 5: Tabs ArrowLeft/ArrowRight keyboard nav (WAI-ARIA tabs pattern).
Fix 6: TabId union type in EngagementDetailPage, cast from string for
type-safe switch on activeTab without breaking Tabs.onChange signature.
Fix 7: intentional comment on UsersAdminPage reset-password aerated row.
Tests: 236/236 (+2 arrow-key assertions in Tabs.test.tsx).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 22:20:51 +02:00
Knacky
790ced4204 fix(frontend): design-review polish — table-compact height, header type-scale, tabs a11y
Fix 1 (A): move row height constraint from min-height on tbody tr
(CSS no-op on table-row) to height: 32px on td (works on table-cell).
Fix 2 (A): table header text-[11px] -> text-[12px] to align with
documented caption scale.
Fix 3: add aria-controls + id to Tabs buttons; wrap active tab content
in role="tabpanel" + aria-labelledby in EngagementDetailPage.
Test: add aria-controls/id assertion to Tabs.test.tsx (234 total).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 22:18:09 +02:00
Knacky
1324a0c8ce docs(design): add tabs / inline banners / compact-table-density to DESIGN.md
Adds:
- Navigation > Sub-page tabs subsection (tab-underline recipes, count pill, ARIA)
- Data Tables: row min-height 44px -> 32px + WCAG SC 2.5.5 rationale
- Toast Notifications > Inline Banners subsection (4 variants table)
Also adds Sprint 11 entry to CHANGELOG.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 22:11:38 +02:00
Knacky
5d34a5e171 test(frontend): add specs for Tabs, AlertBanner, BackLink, useHashTab
4 new spec files adding 21 tests (7+6+4+4). Each component spec
includes brutalism invariant assertions (no rounded-md, no transition-*,
no shadow-*).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 22:11:31 +02:00
Knacky
1819089925 feat(frontend): compact table density (32px row) global
Add table-compact class to all 4 list surfaces: EngagementsListPage,
TemplatesListPage, UsersAdminPage, SimulationList. Remove inline
px-xl py-md from th/td — recipe handles padding. Row border-b moved
to recipe. WCAG SC 2.5.5 tradeoff accepted (BAS operator tool).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 22:11:24 +02:00
Knacky
9a8c5f52ab feat(frontend): add BackLink helper + dedup 3 hand-rolled instances
BackLink: ArrowLeft (14px) + caption-md text-graphite hover:text-primary,
instant. Replaces inline Link patterns in EngagementDetailPage (already
committed), SimulationFormPage, and TemplateFormPage. Also migrates
SimulationFormPage Done/SOC banners to AlertBanner.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 22:11:17 +02:00
Knacky
59eaa342a9 feat(frontend): add AlertBanner component + 4 semantic variants
border-l-4 semantic strip, bg-paper, Lucide icons at size=16.
ARIA role="alert" for error/warn, role="status" for success/info.
No shadow, no radius, no transition.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 22:11:10 +02:00
Knacky
004d075cad feat(frontend): refactor EngagementDetailPage to 3-tab layout
Tabs: Schedule (default) / Description / Simulations, wired via
useHashTab('schedule'). Count pill on Simulations tab. BackLink
replaces hand-rolled Link.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 22:11:04 +02:00
Knacky
bca39dcca7 feat(frontend): add Tabs primitive + useHashTab hook
- useHashTab: pure-TS hook reading window.location.hash, falls back to
  defaultId, hashchange listener cleaned up on unmount
- Tabs: <Tabs items activeId onChange> with tab-underline / tab-underline-active
  recipes and count-pill (rounded-pill exception per DESIGN.md)
- index.css: tab-underline*, tab-count-pill*, alert-*, table-compact recipes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 22:10:59 +02:00
Knacky
89fb38b107 docs(sprint-11): plan spectrum UX port — 4 primitives + compact density global 2026-06-21 22:03:15 +02:00