Skip to content

feat(design): DESIGN.md-driven theming — dark variant, motion, CI gate#3

Merged
BaruchEric merged 7 commits into
mainfrom
claude/distracted-dirac-73d913
Apr 23, 2026
Merged

feat(design): DESIGN.md-driven theming — dark variant, motion, CI gate#3
BaruchEric merged 7 commits into
mainfrom
claude/distracted-dirac-73d913

Conversation

@BaruchEric
Copy link
Copy Markdown
Owner

Summary

Builds on PR #2 (adopting the DESIGN.md spec) with the full theming pipeline, a generator extension for variants + motion, and a CI gate using the upstream @google/design.md linter.

  • Dark variant + theme switchervariants.dark in DESIGN.md drives @media (prefers-color-scheme: dark) + .sui-theme-dark opt-in class. Switcher lives in the Settings popover alongside Model / Layout / Account.
  • Motion tokens — new motion.duration.{fast,base,slow} + motion.easing.{standard,emphasized}. Wired through button / link / progress transitions.
  • Every component themed — alerts, badges, focus rings, progress, input-invalid all read tokens via color-mix(in srgb, var(--sui-colors-*) N%, transparent) so the same hex drives saturated borders and softened backgrounds.
  • AA contrast fixprimary #508cdc#1f6fc7 (3.43 → 5.11), error #dc5a5a#c43d3d (3.71 → 4.75). Dark palette untouched.
  • Component references — alert / badge-default / link entries added to components: so every color token is referenced. Drops the "unused token" warnings.
  • CI gatescripts/lint-design.ts runs @google/design.md lint, fails on errors > 0, surfaces warnings in the log. Wired into .github/workflows/ci.yml.
  • Regression testscripts/design-to-css.test.ts pins the generator contract (5 new tests).

Linter now reports 0 errors, 0 warnings.

Test plan

  • bun run lint:design → 0/0/1
  • bun run lint · typecheck · test (97/97) · build all green
  • Browser: theme switcher toggles System / Light / Dark / Heritage — primary/alert/badge/progress all reskin
  • Browser: primary button in Light renders rgb(31, 111, 199) with white text (AA pass)
  • Agent system prompt includes DESIGN.md; agent named all 10 color tokens by semantic name in a probe
  • CI run on this PR exercises lint:design gate

Mirrors the api/agent.ts change so `bun run playground:full` agents
see the design guide in dev, not just on Vercel.
- DESIGN.md: add variants.dark palette (namespaced extension to the spec)
- Generator: emit each variant as `.sui-theme-<name>`; `dark` also wires
  `@media (prefers-color-scheme: dark) { :root:not(.sui-theme-light) }`
  so OS preference is honored unless explicitly overridden
- Playground: 4-way switcher (System / Light / Dark / Heritage) with
  localStorage persistence. Heritage demonstrates runtime token overrides
  layered on top of class-based variants — proof that the same agent
  output reskins across three palettes with zero component changes.
Every themable component in styles.css now reads a token (with rgba
fallback) instead of hardcoded rgb. Uses color-mix(in srgb, ..., transparent)
for tint/alpha so the same hex can drive both the border and a softened
background without duplicating tokens.

Effect: switching the theme switcher now retouches alerts (info/success/
warning/error), badges, input focus ring, progress bar fill, and input-
error states — not just buttons and links.
…ac-73d913

# Conflicts:
#	playground/index.html
…/link/progress

- DESIGN.md: new `motion:` section (duration.fast/base/slow + easing.standard/
  emphasized) and matching prose on when to use each duration. Framework is
  agent-cadence so transitions lean short and precise — no bounce, no overshoot.
- Generator: add `motion` to TOKEN_GROUPS so the recursive emitter walks it.
- styles.css: button hover/focus color tweens at duration.fast; link color at
  duration.fast; progress fill at duration.base, all via easing.standard (with
  hardcoded fallbacks so consumers who skip the generator still look right).

Result: buttons and links have a distinct hover tween instead of hard-flipping,
progress bars ease into new values. Agents can now reference
`{motion.duration.fast}` in custom component tokens alongside colors/spacing.
- package.json: `lint:design` runs upstream `@google/design.md lint DESIGN.md`
  (WCAG contrast + cross-reference checks). `diff:design` reports token-level
  changes between two DESIGN.md files — useful for PR reviews.
- vitest.config.ts: pick up scripts/**/*.test.ts so generator tests run.
- scripts/design-to-css.test.ts: pins the contract between DESIGN.md and the
  downstream CSS. Runs the generator in-process and asserts :root has every
  semantic token styles.css consumes, motion tokens exist, token references
  resolve to var(), dark variant emits both class + media query, and hex is
  lowercased (biome CSS rule).

First lint:design run already surfaced real findings — contrast warnings on
button-primary (3.43:1) and button-danger (3.71:1) vs white text (AA needs
4.5:1). Left as-is intentionally; darkening the palette is a design call.
Fix contrast (light palette):
- primary  #508cdc → #1f6fc7  (3.43 → 5.11 on white, passes WCAG AA)
- error    #dc5a5a → #c43d3d  (3.71 → 4.75, passes AA)
- link     #6496ff → #2f6fc7  (aligned with primary, readable on light/dark)
- neutral darkened slightly for consistency with the shifted palette
Dark palette unchanged — lighter tones already clear AA on dark ink.

Reference every color in components: (drops all "unreferenced" warnings):
- alert-{info,success,warning,error}.backgroundColor → {colors.*}
- badge-default.backgroundColor                       → {colors.neutral}
- link / link-hover.textColor                         → {colors.link[-hover]}

CI gate:
- scripts/lint-design.ts: runs @google/design.md lint --format=json, prints a
  readable summary, exits non-zero on structural errors. Warnings are logged
  but do not block merges yet (raise the bar when the warning surface is
  clean beyond what's left).
- package.json lint:design points at the new script.
- .github/workflows/ci.yml runs lint:design after build.

Linter now reports 0 errors / 0 warnings.
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
stream-ui Ready Ready Preview, Comment Apr 23, 2026 0:52am

Request Review

@BaruchEric BaruchEric merged commit 9f9e053 into main Apr 23, 2026
3 checks passed
@BaruchEric BaruchEric deleted the claude/distracted-dirac-73d913 branch April 23, 2026 00:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant