feat(frontend): migrate renderer to token-based design system#2535
feat(frontend): migrate renderer to token-based design system#2535Annieeeee11 wants to merge 10 commits into
Conversation
There was a problem hiding this comment.
@Annieeeee11 direction looks good to me, especially centralizing renderer styling around tokens.
Introduce tokens.css as the single source of truth for renderer colors, typography, spacing, motion, and z-index, with Tailwind @theme/@Utility bridges in styles.css. Remove legacy BEM chrome (~1.4k lines), add shared TopbarButton/StatusPill/ResizeHandle components, and adopt semantic utilities across renderer components and shadcn primitives. Update tests for new test IDs and add DESIGN_TOKENS, DESIGN_AUDIT, and MIGRATION_GAPS docs.
52dadf9 to
3098057
Compare
88c2acd to
d15c816
Compare
|
Can you also share screenshots of changes visible in the product behavior/appearance? |
SessionStatusPill referenced workerDisplayStatus without importing it, which crashed the renderer with "workerDisplayStatus is not defined".
Align tests with workerDisplayStatus-driven labels instead of the old activity-based pill text (Idle, Input Needed, Exited).
whoisasx
left a comment
There was a problem hiding this comment.
Reviewed latest head 14aa6f4. The token-system direction looks good and the focused renderer checks pass, but I am holding approval for these fixes: the topbar status semantics changed despite this being framed as an appearance-preserving migration, two tokenized utilities are silently dropped from the built CSS, and the new docs currently leak an invalid Tailwind utility into the renderer build. Also please clean up the trailing whitespace reported by git diff --check in the new docs.
| {label} | ||
| </span> | ||
| ); | ||
| const { label, tone, breathe } = STATUS_PILL[workerDisplayStatus(session)]; |
There was a problem hiding this comment.
[P2] This changes the topbar pill from the raw live activity state to the derived worker display status. An active worker can now show CI failed, Ready, or Done instead of Working, which is a user-visible behavior change even though the PR states appearance and behavior are unchanged. Either keep the old activity-based topbar pill or explicitly call out and product-approve this semantic change.
| data-size={size} | ||
| className={cn( | ||
| "flex w-fit items-center justify-between gap-2 rounded-md border border-border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-border-strong focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[placeholder]:text-muted-foreground data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground", | ||
| "flex w-fit items-center justify-between gap-2 rounded-md border border-border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-border-strong focus-visible:ring-0.75 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[placeholder]:text-muted-foreground data-[size=default]:h-control-board data-[size=sm]:h-control-form *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-icon-base [&_svg:not([class*='text-'])]:text-muted-foreground", |
There was a problem hiding this comment.
[P2] focus-visible:ring-0.75 is not emitted into the production CSS, so this regresses the previous focus-visible:ring-[3px] style and the select loses its intended focus-ring width. Please use an emitted utility such as an arbitrary value, or add a real token that Tailwind generates.
| aria-label={`Rename ${session.title}`} | ||
| autoFocus | ||
| className="min-w-0 flex-1 rounded-[3px] border border-accent bg-transparent px-1 py-px text-[12px] text-foreground outline-none focus-visible:ring-1 focus-visible:ring-accent" | ||
| className="min-w-0 flex-1 rounded-0.75 border border-accent bg-transparent px-1 py-px text-xs text-foreground outline-none focus-visible:ring-1 focus-visible:ring-accent" |
There was a problem hiding this comment.
[P2] rounded-0.75 is also not emitted by the generated CSS, so the rename input silently loses this radius. This should use a valid emitted utility or a defined radius token before we rely on it in migrated components.
| | `text-heading` | `--font-size-heading` | 21 | | ||
| | `text-heading-lg` | `--font-size-heading-lg` | 22 | | ||
|
|
||
| Prefer these utilities over `text-[length:var(--font-size-*)]` in components. |
There was a problem hiding this comment.
[P3] Tailwind scans this markdown literal and emits an invalid .text-[length:var(--font-size-*)] utility, which shows up as a CSS optimizer warning during the renderer build. Please rewrite or break up the example so the docs do not affect generated app CSS.


Summary
Migrates
frontend/src/rendererto a token-based design system so styling is consistent, themeable, and easier to maintain.src/styles/tokens.cssas the single source of truth for colors, typography, spacing, motion, icons, and z-index; wires tokens into Tailwind via@theme/@utilityinstyles.cssstyles.css(~1,450 lines deleted); global CSS now only covers xterm, keyframes, session-split, and resize global stateTopbarButton,StatusPill, andResizeHandleto replace ad-hoc BEM classes and inline patternsui/*primitives to use semantic utilities (text-caption,h-control-form,size-icon-*,z-chrome, etc.) instead of hardcoded valuesindex.htmlsetsdata-themebefore first paint to avoid FOUC; terminal palette reads--color-term-*viaterminal-themes.tsDESIGN_TOKENS.md,DESIGN_AUDIT.md, andMIGRATION_GAPS.md(migration marked complete)Scope: renderer only;
src/landing/intentionally unchanged.Diff: 46 files, ~984 insertions / ~2,122 deletions (net reduction driven by BEM removal).
Test plan
npm run typecheckpassesnpx vitest run src/rendererpassesnpx vite buildsucceeds