Skip to content

[Task] Design token system debt log (drift, redundancy, dual systems) #642

Description

@Astro-Han

Goal

Single tracking log for all design-token system debt — redundant aliases, source-of-truth drift between docs/DESIGN.md and runtime theme.css, and parallel-system overlaps. No commitment to clear every entry on a fixed timeline. Entries are resolved opportunistically as the UI rewrite work in #601 (and follow-ups) touches the relevant surfaces.

Scope and intent

This issue is intentionally not a cleanup PR queue. It is a record so the next person who edits typography, colors, spacing, or theme files can pull from a single place rather than rediscovering the same debts. Each entry below states the current observed state and what decision is required, not a scheduled fix.

Findings

Category A · Real dead tokens and stray hardcoded values (low-risk to clean opportunistically)

Either duplicate an existing token, live outside the docs/DESIGN.md spec, or are hardcoded values that should be token references. Safe to delete or fix the next time someone is in the relevant file for an unrelated reason.

  • --font-size-hierarchy (13px, identical to --font-size-base). 9 callsites in packages/ui are all mechanical, no semantic distinction.
  • --brand-danger and --brand-danger-hover. Upstream-inherited aliases for --error. docs/DESIGN.md uses --error exclusively for the danger semantic (see L326-330). Zero callsites in packages/.
  • Hardcoded border-radius: 6px in packages/ui/src/components/message-part.css L42 (user-message-attachment) and L374. Value is correct (matches --radius-sm = 6px from the project frontmatter) but missed token-ization. Two callsites, both safe to replace with var(--radius-sm).

Category B · DESIGN.md ↔ runtime drift (needs source-of-truth decision)

Where the design source and the runtime disagree. Resolve when the affected component surface is next touched.

  • Light --surface-sunken value. docs/DESIGN.md L135 and docs/design/colors_and_type.css declare #F4F0EC as an independent third neutral tier reserved for inline code and code-block headers. packages/ui/src/styles/theme.css declares #faf9f7 (identical to --bg-cream) and carries the comment light alias → bg-cream; no third neutral tier. The runtime stance contradicts the design source. Decide which is canonical: either DESIGN.md drops the third tier (matching runtime), or runtime restores #F4F0EC (matching design).
  • Dark --surface-sunken is too dark to see inline-code decoration. docs/DESIGN.md reserves --surface-sunken for inline code; in dark theme its value (#16130F) sits below --bg-base (#1A1714), so the decoration disappears. docs/design/ui_kits/desktop/styles.css already routes .pw-agent-text code, .pw-chip, .pw-tool, .pw-input, .pw-kbd to --surface-base (one tier above bg) instead. The fix is either lifting the dark sunken value, or dropping the "sunken" semantic and renaming the token to reflect the actual usage.

Category C · Parallel-system overlap (resolves with rewrite progress)

Two parallel token systems express the same concept. Picking one and deprecating the other is a real design call, not a cleanup.

  • Typography: --type-* vs --font-size-*. docs/DESIGN.md L195-208 specs nine --type-* composite tokens (each bundles weight, size, line-height, family). Only --type-body is actually used (three callsites). The remaining eight (--type-display, --type-h1, --type-h2, --type-h3, --type-caption, --type-mono, --type-mono-small, --type-kbd) have zero component callsites. Components use the older --font-size-* family (45+ callsites for --font-size-small alone). Decide whether the rewrite migrates components to font: var(--type-*), or whether --type-* is dropped in favor of the existing per-property tokens.
  • --font-size-small (13px, identical to --font-size-base). 45 callsites in packages/ui plus three .ts files. The name implies smaller-than-base but the value is the same. Three options to evaluate when the typography decision above is taken: delete and migrate to --font-size-base; re-tune --font-size-small to 12px so the scale (small < base < large) reads honestly; or keep --font-size-small and remove --font-size-base from the public surface.
  • Radii: Tailwind --radius-* vs project --radius-* (same name, different scale, different values). Tailwind utility radii in packages/ui/src/styles/tailwind/index.css L59-63 are rem-based (xs=0.125rem / sm=0.25rem / md=0.375rem / lg=0.5rem / xl=0.875rem → 2 / 4 / 6 / 8 / 14 px). Project radii in docs/DESIGN.md frontmatter L72-76 are explicit px (sm=6 / md=10 / lg=14 / pill=9999). Same name md disagrees on value: Tailwind rounded-md = 6px, project var(--radius-md) = 10px. Components mixing the two namespaces get unexpectedly different geometry — for example dock attachments (packages/app/src/components/prompt-input/image-attachments.tsx) use Tailwind rounded-md and render at 6px, while W1 preview docs/design/preview/message-flow.html originally locked file chips at var(--radius-md) = 10px. Decide whether to align values, or document the dual-namespace as the deliberate design (Tailwind = utility shorthand for fine-grained pixel control, project tokens = product-design coarser scale).

Category D · Already resolved (recorded for completeness, no action)

Closed locally in docs/ only (which is .git/info/exclude'd per AGENTS.md and not in git):

  • --icon-chev was reverted before reaching packages/. All preview and scratch files now use the existing --icon-base. The chevron paragraph in docs/DESIGN.md was rewritten to drop the new-token rationale; the 12-px chev size carries the secondary-symbol hierarchy on its own.
  • --bg-strong removed. Nine real callsites in docs/design/ui_kits/desktop/styles.css rewired to --surface-base (same value as the deleted alias). Dead declarations purged from colors_and_type.css and nine preview files.
  • docs/DESIGN.md frontmatter deviations: ledger expanded from two entries to thirteen, capturing previously inline-only exceptions (kbd off-grid padding, dialog text-only buttons, branch dirty three-button dialog, popover inline search row, discard armed button, branch popover width 280, settings nav width 240, hotkey hover dashed-to-solid, app picker multi-color icon, file-type vendor icons, Lucide library) so the ledger is now the only formal record of sanctioned exceptions.

Not problems (forward-looking spec, keep)

Tokens with zero current callsites that are nonetheless intentional. They are part of the docs/DESIGN.md frontmatter scale and reserved for future components.

  • --radius-pill (9999px). docs/DESIGN.md frontmatter L75 explicitly defines the pill tier ("pill": 9999). Reserved for badge / chip / tag / avatar shapes the rewrite has not yet built.
  • --space-xl (20px), --space-2xl (24px), --space-3xl (32px), --space-4xl (48px), --space-5xl (64px). docs/DESIGN.md frontmatter L62-70 declares the full xs through 5xl spacing scale. Reserved for layouts the rewrite has not yet built.

Pointers

Verification (when an entry is eventually closed)

Whichever Category-A entry ships as a cleanup PR:

  • bun --cwd packages/app run typecheck clean.
  • bun test packages/ui green (theme-parity test ensures pawwork.json mirrors theme.css).
  • grep -rn <removed-token> packages/ returns zero hits after the PR.
  • Visual diff zero for direct aliases (Category A); visual diff inspection required for Category B and C entries that actually change rendered values.

Execution mode

Agent should investigate and propose a plan first for any Category B or C entry. Category A can be cleaned directly when the surrounding code is being modified for another reason; do not open a standalone PR just for Category A.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Low prioritytaskNarrow execution, audit, spike, migration, tracking, or upstream follow-up workuiDesign system and user interface

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions