Skip to content

feat(#138): normalize design tokens — add --color-placeholder, --border-radius, --transition-duration - #189

Merged
jenil merged 1 commit into
v1from
work/138-design-tokens
Aug 12, 2026
Merged

jenil merged 1 commit into
v1from
work/138-design-tokens

Conversation

@jenil

@jenil jenil commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Closes #138.

Summary

Normalize three existing hardcoded design values into a small, documented custom-property API. Defaults preserve rendered output at the current 16px consumer root — this is a value-preserving change unless a consumer overrides the tokens.

Tokens added

Token Default Replaces
--color-placeholder #bdbfc4 hardcoded ::placeholder color (src/_form.css)
--border-radius 4px hardcoded border-radius: 4px on .card, code/kbd, inputs/select/textarea, buttons, and .grouped.gapless first/last child outer corners
--transition-duration 0.2s hardcoded 0.2s in input/button transitions

9 hardcoded sites replaced with var() references across src/_base.css, src/_card.css, src/_form.css. The .grouped.gapless compound border-radius keeps !important; only the outer corners follow the token, inner 0s stay literal (joined-border geometry).

Hardcode inventory / ledger

Candidate Accept/Reject Source locations Default Affected selectors Consumer benefit Compat risk
--color-placeholder Accept src/_form.css:241 #bdbfc4 ::placeholder Match placeholder to brand/theme None — same default
--border-radius (single) Accept src/_base.css:152 (code,kbd), src/_card.css:3 (.card), src/_form.css:17 (inputs), src/_form.css:48 (buttons) 4px 4 component surfaces Single knob for corner rounding None — same default
--border-radius (compound, .grouped.gapless) Accept src/_form.css:115,119 4px (outer corners only) .grouped.gapless > *:first/last-child Override propagates to gapless group outer corners None — !important preserved, inner 0s stay literal
--transition-duration Accept src/_form.css:20,53 0.2s inputs/select/textarea, .button/button One knob for motion speed None — same default

No speculative tokens added (no warning/info/link/breakpoint/spacing/utility tokens). Out-of-scope candidates (e.g. 0.625rem paddings, 2px outline width) were rejected as not genuine customization points.

Changed files (13)

Source (3):

  • src/_base.css — 3 token declarations in :root; code,kbd border-radius → var(--border-radius)
  • src/_card.css — .card border-radius → var(--border-radius)
  • src/_form.css — 6 replacements (2 border-radius, 2 transition-duration, 1 placeholder color, 2 .grouped.gapless compound border-radius)

Generated (2):

  • dist/chota.css, dist/chota.min.css — regenerated via yarn build

Tests (3):

  • test/vrt/api-manifest.json — 3 new customProperties (17 total, 185 selectors unchanged)
  • test/token-overrides.html (NEW) — minimal fixture with :root override proving each token propagates
  • test/vrt/token-overrides.spec.js (NEW) — Chromium-pinned computed-style spec (no screenshots), port 3601

Docs (3):

  • docs/index.html — #customizing :root block lists the 3 new tokens
  • docs/architecture.md — CSS Variables section adds --color-placeholder + new "Component tokens" bullet; removed the stale "not exposed" note
  • MIGRATION.md — new "## Design Tokens" section with before/after table and override example

Config (2):

Validation evidence (local, macOS, Chromium)

Gate Command Exit Result
Stylelint yarn test 0 clean
Build + size gate yarn build 0 Size gate: 3409 bytes (baseline: 3409, ceiling: 4096) PASS
API contract yarn test:api 0 5 passed
VRT (existing baselines) yarn test:vrt 0 101 passed, zero baseline diffs
A11y yarn test:a11y 0 4 passed, no new violations
New spec npx playwright test test/vrt/token-overrides.spec.js --project=chromium 0 1 passed (6 assertions)

Base SHA: 22b2cd1 (v1)
Validation SHA: 5a8b5b2 (work/138-design-tokens)
Browser/OS/viewport: Chromium / macOS / 1280×720 (existing VRT also 375×667)
Size: gzip 3373 → 3409 bytes (+36, 687 bytes under 4096 ceiling)

Live browser verification

Loaded test/token-overrides.html with :root { --border-radius: 0px; --transition-duration: 0.5s; --color-placeholder: #ff0000; } and confirmed via getComputedStyle:

Override Propagated to Computed
--border-radius: 0px .card 0px (was 4px)
--border-radius: 0px .button 0px (was 4px)
--transition-duration: 0.5s .button 0.5s (was 0.2s)
--color-placeholder: #ff0000 ::placeholder rgb(255, 0, 0) (was #bdbfc4)
--border-radius: 0px .grouped.gapless > *:first-child 0px (was 4px 0 0 4px)
--border-radius: 0px .grouped.gapless > *:last-child 0px (was 0 4px 4px 0)

Card Done checklist

  • Every new token maps to an existing, named hardcoded value and is documented with default and affected surfaces (MIGRATION.md table)
  • Placeholder color no longer a stray hardcode where token adopted (bdbfc4 only in :root default)
  • Existing variables and behavior retain compatibility (test:api 5/5 green)
  • Docs, fixture overrides, API test, source, and dist agree (defaults cross-checked across all four)
  • No speculative theme token or dynamic-breakpoint promise was added (only 3 tokens; no spacing/breakpoint/utility tokens)

Notes for review

  • Baseline bump: gzip 3373 → 3409 bytes (+36). Per AGENTS.md, baseline increases require owner approval. Rationale: 3 new :root declarations + var() references in place of literals. 687 bytes under the 4096 ceiling.
  • Two brief deviations, both contained to the new spec file:
    1. Port 3600 → 3601 (breakpoints.spec.js already binds 3600)
    2. Assertion 0px 0px 0px 0px → 0px (Chromium CSSOM serializes four equal corners to a single value; consistent with components.spec.js:208)
  • Local evidence only. CI must pass before merge. Not claiming CI green.
  • Reviewer subagent verdict: APPROVE (all 10 verification areas pass, both deviations acceptable).

Unresolved risk

  • CI behavior unverified locally per AGENTS.md. PR CI must pass before merge.

Out of scope (per card)

No warning/info/link/breakpoint/spacing/utility tokens. No media-query runtime-configurability promise. No default dark palette. No changes to .container, .row, .col-*, .tag, or body.dark.

…er-radius, --transition-duration

Add three component-level CSS custom properties to :root, replacing
previously hardcoded values with var() references. Defaults preserve
rendered output at the current 16px consumer root.

Tokens:
- --color-placeholder: #bdbfc4  (was hardcoded on ::placeholder)
- --border-radius: 4px          (was hardcoded on .card, code/kbd,
                                 inputs, buttons, and .grouped.gapless
                                 outer corners; !important preserved)
- --transition-duration: 0.2s   (was hardcoded on input/button
                                 transitions)

9 hardcoded sites replaced across src/_base.css, src/_card.css,
src/_form.css. API manifest gains 3 customProperties (17 total,
185 selectors unchanged). New test/token-overrides.html fixture +
test/vrt/token-overrides.spec.js (Chromium, computed-style, no
screenshots) prove each token override propagates to every affected
surface. Docs (index.html #customizing, architecture.md) and
MIGRATION.md updated with defaults, before/after table, and override
example.

Size: gzip 3373 -> 3409 bytes (+36, within 4096 ceiling); baseline
updated with #138 rationale. VRT 101/101 green against existing
baselines (zero diffs — token substitutions value-preserving at
default :root). test:api 5/5, test:a11y 4/4, stylelint clean.

Closes #138.
@jenil
jenil force-pushed the work/138-design-tokens branch from 5a8b5b2 to bc8a80f Compare August 12, 2026 02:20
@jenil
jenil marked this pull request as ready for review August 12, 2026 02:24
@jenil
jenil merged commit 3efaa00 into v1 Aug 12, 2026
2 checks passed
jenil added a commit that referenced this pull request Aug 12, 2026
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