feat(web): unify tailwind theme with design tokens + add light palette #208

Closed
opened 2026-04-21 10:28:46 +00:00 by claude-desktop · 0 comments
Collaborator

User story

As a dashboard operator, I want every Tailwind utility class in apps/web to resolve through the design-token system (including a brand-new light palette and a mode switcher), so that every color/size change lives in one place (design/tokens.json) instead of being sprinkled across 36 component files — and follow-up cleanups can rely on a stable token surface.

Context

From the styling audit (2026-04-21):

  • Colors are already clean: bg-bg, text-text-primary, border-border, role/state/stage utilities all flow through tokens.css@theme in index.css. No raw hex in components.
  • Font sizes bypass tokens: ~235 component sites use text-[11px], text-[12px], text-[13px] literals instead of the --ch-font-size-* tokens. The html { zoom: 1.2 } block in index.css is a workaround.
  • Dark-only today: design/tokens.json has no light palette. Dashboard is dark-first, but the option should exist.
  • Two missing size slots: --ch-font-size-caption (for 26 text-[10px] sites) and --ch-font-size-h3 (for 3 text-[14px] sites jumping from body=13 → h2=18).

Acceptance criteria

Tokens

  • design/tokens.json gains a full light palette alongside Tokyo Night Storm dark — every color.* slot (bg, surface, surface-high, border, text-, accent, state., role., stage.).
  • design/tokens.json adds font-size.caption = 10px and font-size.h3 = 14px.
  • apps/web/src/styles/tokens.css regenerated: dark under :root, light under :root[data-theme="light"]. @media (prefers-color-scheme: light) fallback for operators who never toggle.

@theme wiring

  • apps/web/src/styles/index.css @theme block exposes --text-meta, --text-small, --text-body, --text-body-lg, --text-h3, --text-h2, --text-h1, --text-display, --text-caption so text-meta, text-small, etc. become first-class Tailwind utilities.
  • Radius utilities stay canonical: verify rounded-compact, rounded-default, rounded-card, rounded-pill still resolve cleanly.

Mode switcher

  • components/app-shell.tsx (or a dedicated <ThemeToggle>) adds a dark/light toggle in the top bar.
  • Selected mode persists in localStorage under key ch-theme.
  • Initial render reads the persisted value before hydration to avoid FOUC (inline <script> in index.html or equivalent).

Verification

  • bun run build succeeds with no new warnings.
  • Visual smoke: every page (/monitor, /planner, /planner/board, /agents, /stats, /usage, /specs) renders correctly in both palettes.
  • zoom: 1.2 stays in place for now; removing it is scoped to the follower ticket.

Out of scope

  • Migration of the 235 text-[Npx] literals → follower ticket (depends on this).
  • Card radius hierarchy cleanup + rounded-[var(...)] refactor → follower ticket (depends on this).
  • Enforcing the <Button> component in spec-editor forms → independent ticket.
  • Dropping the zoom: 1.2 hack → transitively depends on this.

References

  • Styling audit report in conversation history (2026-04-21) — itemized counts + worst offenders.
  • apps/web/src/styles/tokens.css — current dark-only tokens.
  • apps/web/src/styles/index.css:16-60 — current @theme mapping.
  • apps/web/src/styles/index.css:71-79 — the zoom: 1.2 block that follow-up work can remove.
  • design/tokens.json — DTCG spec source of truth.
## User story As a dashboard operator, I want every Tailwind utility class in `apps/web` to resolve through the design-token system (including a brand-new **light palette** and a mode switcher), so that every color/size change lives in one place (`design/tokens.json`) instead of being sprinkled across 36 component files — and follow-up cleanups can rely on a stable token surface. ## Context From the styling audit (2026-04-21): - **Colors are already clean**: `bg-bg`, `text-text-primary`, `border-border`, role/state/stage utilities all flow through `tokens.css` → `@theme` in `index.css`. No raw hex in components. - **Font sizes bypass tokens**: ~235 component sites use `text-[11px]`, `text-[12px]`, `text-[13px]` literals instead of the `--ch-font-size-*` tokens. The `html { zoom: 1.2 }` block in `index.css` is a workaround. - **Dark-only today**: `design/tokens.json` has no `light` palette. Dashboard is dark-first, but the option should exist. - **Two missing size slots**: `--ch-font-size-caption` (for 26 `text-[10px]` sites) and `--ch-font-size-h3` (for 3 `text-[14px]` sites jumping from body=13 → h2=18). ## Acceptance criteria ### Tokens - [ ] `design/tokens.json` gains a full **light** palette alongside Tokyo Night Storm dark — every `color.*` slot (bg, surface, surface-high, border, text-*, accent, state.*, role.*, stage.*). - [ ] `design/tokens.json` adds `font-size.caption = 10px` and `font-size.h3 = 14px`. - [ ] `apps/web/src/styles/tokens.css` regenerated: dark under `:root`, light under `:root[data-theme="light"]`. `@media (prefers-color-scheme: light)` fallback for operators who never toggle. ### @theme wiring - [ ] `apps/web/src/styles/index.css` `@theme` block exposes `--text-meta`, `--text-small`, `--text-body`, `--text-body-lg`, `--text-h3`, `--text-h2`, `--text-h1`, `--text-display`, `--text-caption` so `text-meta`, `text-small`, etc. become first-class Tailwind utilities. - [ ] Radius utilities stay canonical: verify `rounded-compact`, `rounded-default`, `rounded-card`, `rounded-pill` still resolve cleanly. ### Mode switcher - [ ] `components/app-shell.tsx` (or a dedicated `<ThemeToggle>`) adds a dark/light toggle in the top bar. - [ ] Selected mode persists in localStorage under key `ch-theme`. - [ ] Initial render reads the persisted value before hydration to avoid FOUC (inline `<script>` in `index.html` or equivalent). ### Verification - [ ] `bun run build` succeeds with no new warnings. - [ ] Visual smoke: every page (`/monitor`, `/planner`, `/planner/board`, `/agents`, `/stats`, `/usage`, `/specs`) renders correctly in both palettes. - [ ] `zoom: 1.2` stays in place for now; removing it is scoped to the follower ticket. ## Out of scope - Migration of the 235 `text-[Npx]` literals → follower ticket (depends on this). - Card radius hierarchy cleanup + `rounded-[var(...)]` refactor → follower ticket (depends on this). - Enforcing the `<Button>` component in spec-editor forms → independent ticket. - Dropping the `zoom: 1.2` hack → transitively depends on this. ## References - Styling audit report in conversation history (2026-04-21) — itemized counts + worst offenders. - `apps/web/src/styles/tokens.css` — current dark-only tokens. - `apps/web/src/styles/index.css:16-60` — current `@theme` mapping. - `apps/web/src/styles/index.css:71-79` — the `zoom: 1.2` block that follow-up work can remove. - `design/tokens.json` — DTCG spec source of truth.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
charles/claude-hooks#208
No description provided.