refactor(web): rebuild dashboard UI on shadcn-svelte primitives#97

merged7
t3code/singularity-feed
t3code/refresh-frontend-experience
openedAug 22, 2026byOoliver
View on GitHubTwo-way sync enabledPR last imported 4d ago

Problem

The dashboard had no component layer: buttons, cards, checkboxes, and four independent segmented-control implementations were hand-rolled inline and had drifted apart. Dark mode was 279 per-callsite dark: variants. The three breakdown chart cards (IPChart/ProtocolChart/SpectrumStatsChart, ~2,800 lines) were near-clones sharing 19 identically named functions. A few Svelte 4 idioms survived (createEventDispatcher, a writable store), and chart drag handlers wrote $state on every raw mousemove.

Solution

Five commits, each independently green:

  1. shadcn-svelte foundation — 9 vendored primitives in src/lib/components/ui/, semantic theme tokens (bg-card, text-muted-foreground, …) mapped onto the existing palette (dark surfaces #0a0a0a/#111111/#1a1a1a/#2d2d2d, primary blue-600). Dark mode is now defined once in CSS variables.
  2. Call-site sweep — primitives + tokens across routes, filters, alerts, and netflow components; one shared typed SegmentedControl (with tooltip-on-disabled) replaces all four hand-rolled variants; zero dark: variants remain in app code.
  3. Chart consolidation — shared ChartCard shell (header/controls/resizable well/loading-error-empty states/drag overlays) plus one parameterized BreakdownChart + per-kind config replaces the trio. createEventDispatcher retired app-wide for callback props, rangeSelection moved to a runes class, drag interactions rAF-batched. Chart.js configs preserved verbatim — a future chart-library swap now touches one file.
  4. Cleanup — legacy --color-dark-* tokens removed.
  5. Fix — app-wide Tooltip.Provider in the root layout (bits-ui tooltips throw during SSR without one; found in browser verification, invisible to the home-only e2e test).

Net: authored frontend code shrinks ~2,900 lines; ~1,300 lines of vendored primitives added.

Review fast path

Flows to exercise: home → dataset dashboard → toggle metric/granularity/chart-type controls, drag-select a range on a chart, drill down, reorder chart cards, alerts page (tabs + table), theme toggle, netflow files pages.

Setup: a local dataset DB on the current schema (bucket_coverage table). Older local v2/v3 databases render the chart cards' error states instead — that's pre-existing schema drift, not this PR.

Expected: visually equivalent to before — same layout, density, and palette in both themes. No data-contract or API changes.

Decisions worth knowing:

  • Native <select> and <input type="date"> kept (restyled with tokens) rather than adopting bits-ui Select — simpler and keeps native behavior.
  • bits-ui checkboxes render button[role=checkbox] instead of native inputs; aria labels and visible text preserved throughout.
  • The four chart-state branches (loading / error / no-metrics / empty) are centralized in ChartCard with parameterized copy.

Verification

  • bun run format / lint / typecheck clean (svelte-check: 0 errors, 0 warnings)
  • bun run test:web: 90/90 passing
  • bun run test:e2e: passing
  • Production build (vite build, Cloudflare adapter) succeeds
  • Manually verified home + dashboard in a real browser against live data (light mode)

Remaining manual check: a dark-mode visual pass (tokens make it a single-source change, but eyes on it are cheap insurance).


Directed by Claude Fable 5 (t3 code harness); implementation by gpt-5.6-sol agents via codex exec.

Checks

3 successful
All checks passed
85aba36

Added 7 commits

  • refactor(web): adopt shadcn primitives and semantic tokens across dashboard4e2c98f
  • feat(web): add shadcn-svelte foundation with semantic theme tokensa5918f4
  • refactor(web): consolidate chart trio into shared ChartCard and BreakdownCharta8d043c
  • fix(web): add app-wide tooltip provider required by bits-ui tooltipsbd85d0c
  • chore(web): drop unused legacy dark palette tokensc1e0cdd
  • fix(web): port coverage clamping into consolidated BreakdownChartf9400dd
  • fix(web): convert coverage strip card shell to semantic theme tokens85aba36