refactor(ui): token housekeeping + typography wiring + icon CSS (slice #02, issue #440)#448
Conversation
Reclassify --surface-base-active as a state token (it has full dark-mode coverage and is used by 13+ component CSS files). Move from the UNREGULATED section to the STANDARDS-aligned regulated block in all three CSS sections (light :root, [data-color-scheme="dark"], @media mirror), and add to pawwork.json overrides so the parity test can enforce sync. parity test: 128 → 131 pass (three new assertions for light/dark/media blocks)
…space Shadow and blend-mode values have no place in the color utility namespace; --color-shadow-raised would try to set background-color to a box-shadow string. Remove 9 shadow-* and 1 text-mix-blend-mode entries from script/colors.txt and regenerate tailwind/colors.css accordingly. No callers were using these --color-shadow-* utilities (verified by grep). Shadow values remain accessible as var(--shadow-*) directly.
Replace font-size: 12px with var(--font-size-x-small) and font-size: 13px with var(--font-size-small) across checkbox, switch, radio-group, message-part, and keybind components. Avatar rem sizes are intentionally proportional and left unchanged.
Add [data-color="strong/weak/disabled"] CSS selectors to icon.css so callers can opt into DESIGN.md color states declaratively rather than relying solely on Tailwind text-* overrides. Remove stale commented-out resize property. Add inline comment marking size="small" (16px) as the standard chrome size per DESIGN.md spec.
📝 WalkthroughWalkthroughThe PR standardizes design tokens across the UI theme layer by removing unused shadow tokens, replacing hardcoded font sizes with CSS design token variables in component stylesheets, reordering theme property declarations, enhancing the icon component with explicit color variants, and adding a test suite to validate synchronization between token source files. ChangesDesign Token & Component Standardization
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request standardizes font sizes by replacing hardcoded pixel values with CSS variables across multiple components, including checkbox, keybind, message-part, radio-group, and switch. It also refines the icon component with new color attributes and simplified sizing, updates theme variables for active surfaces, and removes unused shadow and blend mode tokens. A new test was added to ensure synchronization between the color definition file and Tailwind configuration. Feedback was provided to improve the robustness of the token parsing logic in the new test to match the generator script's behavior.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
parseTxtTokens: switch from regex extraction to split(":")[0].substring(2),
matching the exact logic in tailwind.ts. The old regex truncated names at
the first non-[a-z0-9-] character (e.g. underscore), producing misleading
comparison errors.
parseCssTokens: relax [a-z][a-z0-9-]* to [^\s:]+ so the backreference
correctly handles any character the generator accepts.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/ui/test/colors-generation.test.ts (1)
44-60: ⚡ Quick winGood coverage, but this does not fully enforce 1:1 token sync.
Nice bidirectional checks. One gap: Line 45 and Line 54 convert to
Set, so duplicate entries in either file won’t fail the test even though the PR objective says 1:1 consistency. Add a duplicate-count assertion (or compare frequency maps) for both parsed lists.Proposed patch
const txtTokens = parseTxtTokens(COLORS_TXT) const cssTokens = parseCssTokens(COLORS_CSS) + +function countByToken(tokens: string[]): Map<string, number> { + const map = new Map<string, number>() + for (const t of tokens) map.set(t, (map.get(t) ?? 0) + 1) + return map +} test("every colors.txt token has a --color-X: var(--X) entry in colors.css", () => { const cssSet = new Set(cssTokens) const missing = txtTokens.filter((t) => !cssSet.has(t)) @@ ).toEqual([]) }) test("every colors.css entry has a corresponding token in colors.txt", () => { const txtSet = new Set(txtTokens) const orphan = cssTokens.filter((t) => !txtSet.has(t)) @@ ).toEqual([]) }) + +test("token cardinality matches 1:1 between colors.txt and colors.css", () => { + const txtCounts = countByToken(txtTokens) + const cssCounts = countByToken(cssTokens) + expect([...txtCounts.entries()].sort()).toEqual([...cssCounts.entries()].sort()) +})🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/ui/test/colors-generation.test.ts` around lines 44 - 60, The tests use Set conversion (cssSet, txtSet) so duplicate tokens in cssTokens or txtTokens are ignored; update the two tests ("every colors.txt token has..." and "every colors.css entry has...") to assert there are no duplicates by checking that cssTokens.length === new Set(cssTokens).size and txtTokens.length === new Set(txtTokens).size (or alternatively build frequency maps for cssTokens and txtTokens and assert every token has count === 1), then keep the existing bidirectional membership assertions (missing/orphan) to enforce true 1:1 sync between cssTokens and txtTokens.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@packages/ui/test/colors-generation.test.ts`:
- Around line 44-60: The tests use Set conversion (cssSet, txtSet) so duplicate
tokens in cssTokens or txtTokens are ignored; update the two tests ("every
colors.txt token has..." and "every colors.css entry has...") to assert there
are no duplicates by checking that cssTokens.length === new Set(cssTokens).size
and txtTokens.length === new Set(txtTokens).size (or alternatively build
frequency maps for cssTokens and txtTokens and assert every token has count ===
1), then keep the existing bidirectional membership assertions (missing/orphan)
to enforce true 1:1 sync between cssTokens and txtTokens.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: ef2d309a-feee-4a86-9a41-b3c6343b731b
📒 Files selected for processing (11)
packages/ui/script/colors.txtpackages/ui/src/components/checkbox.csspackages/ui/src/components/icon.csspackages/ui/src/components/keybind.csspackages/ui/src/components/message-part.csspackages/ui/src/components/radio-group.csspackages/ui/src/components/switch.csspackages/ui/src/styles/tailwind/colors.csspackages/ui/src/styles/theme.csspackages/ui/src/theme/themes/pawwork.jsonpackages/ui/test/colors-generation.test.ts
💤 Files with no reviewable changes (2)
- packages/ui/src/styles/tailwind/colors.css
- packages/ui/script/colors.txt
Set conversion in the bidirectional membership tests silently ignores duplicate entries. Add two explicit no-duplicates assertions so accidental duplicate lines in colors.txt (and corresponding generated entries in colors.css) are caught early.
|
Fixed in d1b5605. Added two explicit no-duplicates tests before the existing bidirectional membership checks: Used |
Summary
--surface-base-activefrom the UNREGULATED section to the REGULATED section intheme.css(light:root,[data-color-scheme="dark"], and@mediamirror). Syncspawwork.jsonoverrides. Parity test: 128 → 131 pass.test/colors-generation.test.ts) that enforces sync betweenscript/colors.txtandtailwind/colors.css: every token in the source must have a corresponding--color-X: var(--X)entry and vice versa. Planned in slice 01 PR feat(ui): token layer + rename to STANDARDS (slice #01) #442 Risk Note §3.--shadow-*and 1--text-mix-blend-modeentries fromscript/colors.txtand regeneratestailwind/colors.css. These tokens were polluting the--color-*Tailwind namespace (e.g.--color-shadow-raised), which would attempt to setbackground-colorto a box-shadow string. No callers used these utilities.font-size: 12px/font-size: 13pxliterals withvar(--font-size-x-small)/var(--font-size-small)acrosscheckbox.css,switch.css,radio-group.css,message-part.css, andkeybind.css. Avatar rem values are intentionally proportional and left unchanged.[data-color="strong/weak/disabled"]CSS selectors toicon.cssso callers can opt into DESIGN.md color states declaratively. Removes stale commented-out property. Documentssize="small"(16px) as the standard chrome size.Why
Carries over three items deferred from slice 01 (PR #442): the
--surface-base-activeclassification, the colors consistency test, and the shadow namespace fix. Adds typography and icon CSS housekeeping as the code-level foundation for slice 02 per issue #440.Related Issue
Refs #440 (umbrella). This PR is slice 02 of eleven.
Human Review Status
Pending. A human should make the final merge decision after reviewing the final diff and verification evidence.
Review Focus
--surface-base-activeplacement: confirm it now appears before theUNREGULATED TOKENScomment in all three CSS blocks and that the parity test enforces its sync withpawwork.json.--color-shadow-*or--color-text-mix-blend-modeentries remain; shadow utilities (shadow-xs,shadow-md) intailwind/index.cssare separate and correct.12px→var(--font-size-x-small),13px→var(--font-size-small)); no layout changes expected.Risk Notes
--color-shadow-*removal: any CSS that happened to usebg-shadow-raisedetc. as a Tailwind class would silently lose its style. Verified by grep: no callers exist inpackages/app/srcorpackages/ui/src.--font-size-x-smalland--font-size-smallresolve to the same pixel values (12px,13px) as the literals they replace. Zero visual change at current token values.session-diff.test.tsfailures are pre-existing (present before slice 01; confirmed by git log thatsession-diff.tswas not touched).How To Verify
Screenshots or Recordings
No visible UI changes in this PR. All changes are CSS token plumbing, test coverage, and namespace cleanup.
Checklist
dev, and my PR title and commit messages use Conventional Commits in EnglishSummary by CodeRabbit
Chores
Style
Tests