7.2 KiB
7.2 KiB
T01 — Styling Inventory + Drift Map
Date: 2026-03-27
Project: recipe-manager/frontend
Task: T01 — Styling Inventory + Drift Map
Scope audited
- Token sources:
src/styles/tokens.css,src/theme.ts,frontend/tailwind.config.js - Shared styling layer:
src/index.css(ui-*primitives) - Legacy stylesheet:
src/App.css - App shell + representative screens/components:
src/App.tsxsrc/pages/RecipeListPage.tsxsrc/pages/RecipeDetailPage.tsxsrc/pages/CookModePage.tsxsrc/pages/ImportUrlPage.tsxsrc/pages/NotFoundPage.tsxsrc/components/RecipeCard.tsxsrc/components/RecipeForm.tsxsrc/components/TagSelector.tsxsrc/components/Toast.tsxsrc/components/MissionControlPanel.tsxsrc/components/ErrorBoundary.tsx
1) Where styling primitives currently live
Canonical CSS token surface (already strong)
src/styles/tokens.css- semantic color, typography, spacing, radius, shadow, focus, gradients
- includes dark-mode token overrides
Utility-class primitives (already present)
src/index.css@layer components defines:.ui-page,.ui-section,.ui-card.ui-btn,.ui-btn-primary,.ui-btn-secondary.ui-input,.ui-textarea,.ui-select.ui-chip,.ui-badge
- Also contains global focus-visible behavior and utility legacy classes (
.card,.shadow-card,animate-slide-in)
Tailwind token mapping
frontend/tailwind.config.jsmaps many Tailwind theme keys to CSS vars (good bridge)
Parallel TS token layer (drift risk)
src/theme.tsduplicates many token values fromtokens.csscolors,typography,spacing,radius,shadows,componentStyles
Legacy stylesheet
src/App.csscontains Vite/demo-era nested selectors (#next-steps,.hero,.counter, etc.)- not imported by
main.tsxor other src files in current app
2) Systems currently being mixed
- UI primitives + token vars (
ui-*,var(--...)) - Raw Tailwind palette utilities (
bg-blue-*,text-slate-*,border-gray-*, etc.) - Inline style objects via
theme.ts(style={{ borderRadius: radius.lg }},boxShadow: shadows.card) - One-off arbitrary values (
hover:[box-shadow:var(--shadow-hover)],shadow-[...]) - Legacy class debt (
App.css, and old helper classes inindex.css)
Result: there is no enforced single styling path; authors can pick multiple parallel approaches in the same file.
3) Inventory by file (top-level pages + shared components)
Legend:
- A = ui-* primitives + var tokens (preferred direction)
- B = raw Tailwind palette utilities (non-tokenized drift)
- C = inline
theme.tsstyle objects - D = legacy/older pattern
App shell
src/App.tsx→ B-heavy- Header/nav/footer use many
blue/slate/grayclasses and custom focus ring colors - Does not use
ui-page,ui-section,ui-btncontract
- Header/nav/footer use many
Pages
src/pages/RecipeListPage.tsx→ A + C mix (plus some B)- strong
ui-*adoption - frequent inline radius/style injections from
theme.ts
- strong
src/pages/RecipeDetailPage.tsx→ A + B + C mixed- uses many
ui-*classes but also many non-token Tailwind palette classes and inline styles
- uses many
src/pages/CookModePage.tsx→ B-only (high drift)- almost entirely gray/blue/green/red Tailwind palette utilities
- no
ui-*shell/primitives
src/pages/ImportUrlPage.tsx→ B + C (high drift)- heavily uses slate/blue/indigo/green palette classes
- inline radius/progress width styles
src/pages/NotFoundPage.tsx→ B-only
Shared components
src/components/RecipeForm.tsx→ A-dominantsrc/components/TagSelector.tsx→ A-dominant + tiny Csrc/components/RecipeCard.tsx→ A + C mixedsrc/components/Toast.tsx→ C-dominant- visual appearance mostly from
theme.tsinline styles
- visual appearance mostly from
src/components/MissionControlPanel.tsx→ B-onlysrc/components/ErrorBoundary.tsx→ B-only
Approximate drift signal (quick scan)
- Highest raw palette concentration:
CookModePage,ImportUrlPage,App.tsx,RecipeDetailPage - Highest inline-style concentration:
RecipeListPage,RecipeCard,Toast
4) Representative drift hotspots
-
App.tsx(app shell)- Entire global frame (header/nav/footer) is on blue/slate palette utilities
- creates visual disconnect from tokenized warm palette used in recipe surfaces
-
CookModePage.tsx- Separate visual language (blue/gray success/error blocks) and no
ui-*primitives - likely to regress independently if token theme changes
- Separate visual language (blue/gray success/error blocks) and no
-
ImportUrlPage.tsx- Similar drift pattern to CookModePage; raw utility palette + custom gradients
-
RecipeDetailPage.tsx- Mixed approach in same component: token vars + ui-* + raw palette + inline styles
- hard to predict and maintain consistency
-
Toast.tsx+theme.tscoupling- toast visuals encoded in TS style objects instead of ui primitives/token classes
-
App.css+ legacy selectors inindex.cssApp.cssappears unused yet present.card/.shadow-cardcoexist withui-card, increasing ambiguity
5) Highest-risk problem areas
- Token drift risk: same values duplicated in
tokens.cssandtheme.ts. - App-shell inconsistency risk:
App.tsxnot on design-system primitives. - Page-level divergence risk: CookMode/Import URL/NotFound/MissionControl use different style dialect than core recipe pages.
- Maintainability risk: inline style overrides (
borderRadius,boxShadow) bypass primitive contract and encourage per-component customization. - Regression risk: no guardrails prevent new raw palette utilities in future UI work.
6) First conversion targets (for stabilization wave)
src/App.tsx(global shell contract)src/components/MissionControlPanel.tsx(small, easy, high-visibility drift)src/pages/CookModePage.tsx(largest isolated drift surface)src/pages/ImportUrlPage.tsx(same drift pattern as CookMode)src/components/Toast.tsx(inline-style dependency cleanup)
7) Acceptance criteria for stabilization work (T02+)
A stabilization pass is accepted when all are true:
-
Single token authority
- CSS vars in
tokens.cssare canonical. theme.tsno longer independently defines conflicting visual token values.
- CSS vars in
-
Primitive contract adoption
- app shell + major pages use shared
ui-*primitives (or wrapper components built from them). - new features avoid ad-hoc color utilities outside tokenized scheme.
- app shell + major pages use shared
-
Inline-style reduction
- no routine radius/shadow/color inline overrides where equivalent primitive/token class exists.
-
Legacy debt disposition
App.cssremoved or explicitly retained with documented rationale.- overlapping legacy helpers (
.card,.shadow-card) either standardized or deprecated.
-
Governance check
- lightweight styling checklist/doc exists and is referenced in workflow.
8) Suggested next task after T01
T02 — Canonical Token Source Lock
- lock CSS tokens as source of truth
- redefine
theme.tsas typed accessor only (or trim to non-visual helpers) - document token contract before broad conversion starts