10 KiB
phase, slug, status, shadcn_initialized, preset, created
| phase | slug | status | shadcn_initialized | preset | created |
|---|---|---|---|---|---|
| 5 | design-system-token-rework | draft | true | new-york / neutral / lucide | 2026-04-20 |
Phase 5 — UI Design Contract
Visual and interaction contract for Phase 5: Design System Token Rework. Generated by gsd-ui-researcher, verified by gsd-ui-checker.
This phase is a pure token and spacing rework — no new components, no new features. Every entry in this contract describes what must be TRUE after the change, not before.
Design System
| Property | Value | Source |
|---|---|---|
| Tool | shadcn/ui | components.json |
| Style | new-york | components.json |
| Preset | neutral base, cssVariables: true | components.json |
| Component library | Radix UI (via shadcn) | components.json |
| Icon library | lucide-react | components.json |
| Font | Inter (--font-sans) | src/index.css |
Spacing Scale
Declared values (all multiples of 4):
| Token | px Value | Tailwind Class | Usage |
|---|---|---|---|
| xs | 4px | gap-1 / p-1 | Icon gaps, inline tight spacing |
| sm | 8px | gap-2 / p-2 | Compact inline elements, badge padding |
| md | 16px | gap-4 / p-4 | Default inline element spacing |
| lg | 24px | gap-6 / p-6 | Card internal padding (upgraded from p-4) |
| xl | 32px | gap-8 | Section gaps between cards and sections (upgraded from gap-6) |
| 2xl | 48px | gap-12 | Major section breaks, page-level vertical rhythm |
| 3xl | 64px | py-16 | Auth page vertical centering, hero areas |
Phase 5 spacing changes (from CONTEXT.md):
- Card internal padding:
p-4→p-6across all 9 pages - Section gaps:
gap-4→gap-6,gap-6→gap-8across all pages - Page header bottom margin: standardize to
mb-6everywhere - Section-to-section gap: standardize to
gap-8
Exceptions: none — 8-point scale applies without exception.
Typography
| Role | Size | Tailwind | Weight | Weight Class | Line Height | Usage |
|---|---|---|---|---|---|---|
| Caption | 12px | text-xs | 400 | font-normal | 1.5 | Subtitles, secondary metadata |
| Body / Label | 14px | text-sm | 500 | font-medium | 1.5 | Table cells, form labels, card labels, stat subtitles |
| Base | 16px | text-base | 500 | font-medium | 1.5 | Card titles (e.g. chart section headings) |
| Heading | 24px | text-2xl | 600 | font-semibold | 1.2 | Page titles (PageShell h1), auth card titles, template names |
Source: Existing usage in PageShell, StatCard, DashboardPage, LoginPage, RegisterPage confirmed these four sizes as the complete in-use set.
Weights used: exactly 2 — font-medium (500) for body/data, font-semibold (600) for headings. The rare font-bold (700) occurrences in StatCard value display are reclassified as font-semibold for consistency.
Color
Base UI Tokens (post-rework values)
| Role | OKLCH Value | Usage |
|---|---|---|
| Background (dominant, 60%) | oklch(0.98 0.01 260) | Page background — chroma lifted 0.005→0.01 for subtle warmth |
| Card / Popover (secondary, 30%) | oklch(1 0 0) | Cards, modals, popovers, sidebar surface |
| Sidebar | oklch(0.97 0.008 260) | Sidebar background — no change |
| Primary accent (10%) | oklch(0.55 0.15 260) | Active nav items, primary buttons, focus rings |
| Secondary / Muted | oklch(0.93 0.02 260) | Secondary buttons, muted chip backgrounds |
| Border / Input | oklch(0.88 0.01 260) | All borders and input outlines |
| Destructive | oklch(0.6 0.2 25) | Delete actions, error alerts only |
Accent reserved for: primary action buttons, active sidebar navigation item, focus ring outlines, primary CTA buttons. No other elements may use the primary OKLCH(0.55 0.15 260) value.
Category Text Colors (WCAG 4.5:1 contrast on white — no change to lightness/chroma)
| Token | OKLCH Value | Hue |
|---|---|---|
| --color-income | oklch(0.55 0.17 155) | Green |
| --color-bill | oklch(0.55 0.17 25) | Orange-red |
| --color-variable-expense | oklch(0.58 0.16 50) | Amber |
| --color-debt | oklch(0.52 0.18 355) | Red |
| --color-saving | oklch(0.55 0.16 220) | Blue |
| --color-investment | oklch(0.55 0.16 285) | Violet |
Category Fill Colors (post-rework — chroma raised to 0.22+)
These replace the current fill tokens (C=0.18-0.20). Exact values are at Claude's discretion per CONTEXT.md as long as chroma >= 0.22 and the fills remain visually distinct from each other.
| Token | Target OKLCH | Constraint |
|---|---|---|
| --color-income-fill | oklch(0.72 0.22 155) | C >= 0.22, L ~0.70-0.75 |
| --color-bill-fill | oklch(0.70 0.22 25) | C >= 0.22, L ~0.68-0.73 |
| --color-variable-expense-fill | oklch(0.74 0.22 50) | C >= 0.22, L ~0.70-0.76 |
| --color-debt-fill | oklch(0.66 0.23 355) | C >= 0.22, L ~0.64-0.70 |
| --color-saving-fill | oklch(0.72 0.22 220) | C >= 0.22, L ~0.70-0.75 |
| --color-investment-fill | oklch(0.68 0.22 285) | C >= 0.22, L ~0.65-0.72 |
Chart Colors (post-rework — aligned to fill tokens)
The --color-chart-1 through --color-chart-5 variables are REMOVED. Chart components reference --color-*-fill tokens directly. This eliminates the duplicate color system.
| Removed | Replaced by |
|---|---|
| --color-chart-1 | --color-income-fill |
| --color-chart-2 | --color-bill-fill |
| --color-chart-3 | --color-variable-expense-fill |
| --color-chart-4 | --color-debt-fill |
| --color-chart-5 | --color-saving-fill |
Corner Radius
| Token | Current Value | Post-Rework Value | Effect |
|---|---|---|---|
| --radius | 0.625rem (10px) | 0rem (0px) | All shadcn components become sharp-cornered |
Third-party overrides required (applied via CSS selectors in src/index.css):
- Recharts bar elements: force
rx="0" ry="0"or CSSborder-radius: 0 - Sonner toast container: override
.sonner-toastborder-radius to 0
Copywriting Contract
Phase 5 is a pure visual rework — no new user-facing copy is introduced. The following existing copy elements remain unchanged and are documented here as the confirmed contract.
| Element | Copy | Notes |
|---|---|---|
| Primary CTA (Budget List) | "New Budget" | Existing — unchanged |
| Primary CTA (Template) | "Add item" | Existing — unchanged |
| Primary CTA (Categories) | "New Category" | Existing — unchanged |
| Empty state (Dashboard) | Translation key: dashboard.noBudgetForMonth |
Existing — no copy changes this phase |
| Error state (auth forms) | Translation key: auth.error + specific message |
Existing — no copy changes this phase |
| Destructive actions | None introduced in this phase | Token rework only |
No new destructive actions are introduced. No new confirmation dialogs. No new empty states.
Component Inventory
Components affected by token changes (no code changes required — token cascade handles it):
| Component | Location | Rounding Source | Change Required |
|---|---|---|---|
| Button | src/components/ui/button.tsx | --radius token | Automatic via --radius: 0 |
| Card | src/components/ui/card.tsx | --radius token | Automatic; padding class updated to p-6 |
| Input | src/components/ui/input.tsx | --radius token | Automatic via --radius: 0 |
| Badge | src/components/ui/badge.tsx | --radius token | Automatic via --radius: 0 |
| Select | src/components/ui/select.tsx | --radius token | Automatic via --radius: 0 |
| Sheet | src/components/ui/sheet.tsx | --radius token | Automatic via --radius: 0 |
| Dialog | src/components/ui/dialog.tsx | --radius token | Automatic via --radius: 0 |
| Popover | src/components/ui/popover.tsx | --radius token | Automatic via --radius: 0 |
| Sidebar | src/components/ui/sidebar.tsx | --radius token | Automatic via --radius: 0 |
| Dropdown Menu | src/components/ui/dropdown-menu.tsx | --radius token | Automatic via --radius: 0 |
| Recharts bars | SpendBarChart, IncomeBarChart | SVG rx/ry attrs | Explicit CSS override needed |
| Sonner toasts | src/components/ui/sonner.tsx | Sonner inline styles | CSS selector override needed |
| Category swatches | CategoriesPage, CategorySection | Hardcoded rounded-* | Audit and remove rounded-* classes |
| Budget progress bars | BudgetDetailPage | Hardcoded rounded-* | Audit and remove rounded-* classes |
Pages to audit for inline rounded-* classes (must be zero after this phase):
- DashboardPage — CategorySection swatches, StatCard
- BudgetListPage — budget item rows
- BudgetDetailPage — progress bars, budget row items
- TemplatePage — template item rows, category group headers
- CategoriesPage — category color swatches
- QuickAddPage — picker items
- SettingsPage — form elements
- LoginPage — auth card
- RegisterPage — auth card
Registry Safety
| Registry | Blocks Used | Safety Gate |
|---|---|---|
| shadcn official (new-york) | button, card, badge, input, label, select, sheet, dialog, popover, sidebar, dropdown-menu, separator, skeleton, table, tooltip, sonner, chart, collapsible | not required |
| Third-party | none | not applicable |
No third-party registries. No vetting gate required.
Interaction Contract
Phase 5 introduces no new interaction patterns. Existing interactions are preserved. The following are confirmed unchanged:
- Collapsible sections: 200ms ease-out open/close animation (--animate-collapsible-open/close) — no change
- Sidebar navigation: active state uses primary color — no change to behavior
- Form validation: error states use
--color-destructive— no change - Chart tooltips: Recharts default — style override via chart.tsx config only
Visual Regression Checklist
The executor must perform a manual visual pass after all token changes confirming:
- No pill buttons visible on any of the 9 pages
- No rounded cards visible on any of the 9 pages
- No rounded inputs visible on any of the 9 pages
- Category fill colors are visibly colorful against white (not grey-tinted)
- Category text colors still appear dark/readable (not washed out by chroma increase)
- Section gaps feel generous — no visual crowding between cards
- Card internal padding feels spacious — content not flush against card edges
- Page headers have consistent bottom margin before first content section
- Recharts bars are square-ended (no rounded caps)
- Sonner toasts have sharp corners
Checker Sign-Off
- Dimension 1 Copywriting: PASS
- Dimension 2 Visuals: PASS
- Dimension 3 Color: PASS
- Dimension 4 Typography: PASS
- Dimension 5 Spacing: PASS
- Dimension 6 Registry Safety: PASS
Approval: pending