Skip to content

Design System — Status & Plan

Purpose: single place to re-orient on the frontend-core design-system effort without re-investigating. Update this file as state changes. Branch: claude/design-system-progress-F155f.

Last verified: 2026-05-28 · Owner: design-system track


1. One-line status

DECISION MADE (2026-05-29): Option C (hybrid) — shadcn/ui base + selective in-house extensions. The shadcn base is installed on this branch and builds green (Tailwind v4 + vendored components/ui/* + /design-system gallery). Canonical ARC-ADR-008 written (Option C); the in-house (#78) and figma-code-connect (#72) ADR-008 drafts are superseded.

  • Base (done): shadcn — common visual language, copy-in/fork, extend via npx shadcn add.
  • Extension (planned): bespoke data-viz primitives shadcn lacks (Sparkline, SmallMultiples, Numeric, Annotation), rebuilt on shadcn tokens. Scope being confirmed with owner.
  • Brand/visual: deferred to a Claude-design pass (owner driving). #78's visual execution + messy Figma rejected; only the functional data-viz primitives are salvaged.

Remaining: confirm extension scope → port data-viz primitives → migrate existing screens → close superseded PRs (#41/#65/#66/#72/#78).


2. What's merged on main (the foundation) ✅

Piece Location Notes
Design tokens (W3C DTCG) contract/design-tokens.json + .schema.json color, spacing, radius, type, motion, shadow, z. Real values. (#82)
Component API convention contract/components/README.md <Name>.api.ts pattern + token bindings + SemVer ceremony. No .api.ts files written yet. (#82)
Runtime theming app/theme.css, app/theme/ThemeToggle.tsx CSS custom props, light+dark, full WCAG AA contrast audit, no-flash toggle. In use.
Storybook .storybook/, 4 *.stories.tsx v10 + a11y addon. Only 4 stories (Citation/Ingest/Cockpit/DeleteConfirm). (#40)

docs/decisions/ on main holds ADR-002/003/006/007. No ADR-008 is merged.


3. The blocker: one decision + one ADR collision ⚠️

📄 Decision brief written: DECISION-shadcn-vs-inhouse.md — compares A/B, adds a hybrid Option C, and recommends. Still awaiting the call.

3a. Strategic fork (must pick one)

  • Path A — shadcn/ui (PR #41 spike): bake-off measured shadcn ~5× lighter than MUI (~14 KB vs ~75 KB all-in), RSC-native, vendored in-repo, CSS-var theming continuous with existing theme.css. Recommended by the spike.
  • Path B — in-house "untool.ai" DS (PR #78): bespoke --ut-* token layer + 12 hand-built primitives + homegrown "Code Connect Lite". Chosen inside #78, overriding the spike — but never ratified by merging.

Decision was effectively made in a draft PR (#78 → Path B) but is not ratified. Both bets remain open and mutually exclusive.

3b. ADR-008 is triple-booked

Three different decisions all claim ARC-ADR-008 across branches: | Branch/PR | ADR-008 filename | Decision | |---|---|---| | #41 | ARC-ADR-008-frontend-design-system.md | shadcn/ui | | #72 | ARC-ADR-008-figma-code-connect-lite.md | official @figma/code-connect | | #78 | ARC-ADR-008-untool-design-system-and-code-connect-lite.md | in-house DS + homegrown Code Connect |

Action: exactly one ADR-008 should land on main; the others renumber or close.


4. Open PR inventory

PR Title Base State Disposition
#78 untool.ai DS + Code Connect Lite — consolidated, wired to live Figma main draft, 75 files, +8982/−910 Keystone. Absorbs #65/#66/#72. CI/Storybook/plugin boxes unchecked.
#79 Migrate DeleteConfirmCard onto DS primitives #78 branch draft Stacked on #78; lands after it.
#41 Bake-off spike: shadcn/ui over MUI main draft Decision input. "Not for merge as-is." Loses if Path B chosen.
#65 untool brand identity + DS v0 main draft Superseded by #78 (content imported).
#66 Code Connect Lite (homegrown) main draft Superseded by #78.
#72 Official @figma/code-connect lite pilot main draft Superseded by #78 (shape examples kept).
#68 Figma MCP integration verification docs main draft Orthogonal docs.
#70 Replace hardcoded CSS values with tokens main draft Orthogonal token-drift cleanup; can land independently.

Related but not DS-core: #62 (iOS epic — mirrors components), #51 (layered nav shell), #71 (Figma Code Connect issue).


5. Figma — verified 2026-05-28 ✅

Authenticated as Nicky Clarke / Untool.ai (pro). File iBY4OonbLshdzBnqOg2WUC ("Untool.ai · frontend-core · Design System") is real and populated — matches #78's "intentionally simple v0" caveat (real node IDs for the registry to anchor; designers re-author later).

Claim vs reality: - ✔ Wordmark + Text/Surface/Rule/Field/Numeric/Sparkline/SmallMultiples/Annotation/Stack present - ✔ Button component set ×4 (primary/secondary/ghost/destructive) - ⚠️ Badge = 4 tones in Figma (Draft/Indexing/Error/Ready), but #78 claims 5 → code↔Figma drift; figma:verify should catch - ⚠️ Inline primitive folded into Stack (not a separate node) - ⚠️ v0 only: single page/artboard, programmatic placement, visible layout overlaps, no variables/auto-layout

Library check done (get_libraries, 2026-05-29): the file subscribes to Material 3, Figma's Simple Design System, and the Apple iOS/macOS/watchOS/visionOS kits — i.e. the "in-house" file is scaffolded on external UI kits today. Still not confirmed: whether this file itself is published as a consumable Team Library (get_libraries lists libraries added to the file, not its own publish state) — must check manually in Figma Assets → publish. Until published, downstream files + the #62 iOS mirror can't consume it. Detail in the decision brief appendix.

Still open from #78's own checklist: designers re-author the 12 components · populate remaining 23 PENDING registry entries · run the Figma-plugin Dev Mode sync.


6. Next actions (ordered)

  1. Decide Path A (shadcn/ui) vs Path B (in-house untool DS). Everything else is downstream.
  2. Optional aid: one-page decision brief comparing #41 vs #78.
  3. Ratify one ADR-008 on main; renumber/close the other two.
  4. Resolve the Badge 4-vs-5 drift before #78 merges.
  5. Get #78 to merge-ready (if Path B): clear CI/Storybook/plugin checklist; then close #65/#66/#72.
  6. Land #70 (token-drift cleanup) — independent, low-risk, can go anytime.
  7. Confirm Figma is a published library (manual: Assets → publish); schedule designer re-author pass.
  8. CI hygiene (optional): docs-only PRs trip false-red gates because perf.yml/e2e.yml/ci.yml all run on every PR on one contended [self-hosted, docker-local] runner. On PR #93, all three of build/E2E/Lighthouse went red while being provably unrelated to a one-file docs change (build reproduces 100% clean locally; E2E is the pre-existing #88 mock mismatch; Lighthouse died in 60s and is masked by || true). Consider paths-ignore for docs or a docs-safe required-check shim — but mind the branch-protection "required check never reports" gotcha before adding paths-ignore.

7. Key references

  • Figma file: https://www.figma.com/design/iBY4OonbLshdzBnqOg2WUC/Untool-ai-frontend-core-Design-System
  • Tokens: contract/design-tokens.json · Theming: app/theme.css · Components convention: contract/components/README.md
  • ADRs on main: docs/decisions/ (002/003/006/007 — no 008 yet)
  • Hub contracts registry rows: FE-1 (tokens), FE-2 (component API contracts)