Add semantic color tokens — --success / --warning / --danger / --info — and migrate primitives off inlined hex #149

Closed
opened 2026-06-19 18:30:13 +00:00 by james · 0 comments
Owner

Follow-up from #139 (ADR-0024). The accent semantic in the Carol DS surfaces as a three-token set — --accent / --accent-subtle / --accent-text — that themes override and components consume by name. The four other DS-recognised semantics (success / warning / danger / info) don't have that treatment yet: #139's primitives inline literal hex values for them, with hand-written [data-theme="dark"] overrides per component.

That's a real ergonomic + correctness gap:

  • Drift surface. Today four files (Badge.module.css, Field.module.css, Input.module.css, Textarea.module.css, Select.module.css) each carry their own copies of the four semantic colour pairs plus their dark-mode overrides. A future tweak to "the warning amber" has to touch every file or risk a mismatch.
  • Pattern mismatch. The accent flow is the model: components write var(--accent-subtle) + var(--accent-text) and the theme decides what the actual colour is. The semantics deserve the same shape.
  • Theme-switch fragility. Each [data-theme="dark"] override in component CSS is a place future themes (auto, high-contrast, etc.) have to be patched. A token-level definition is patched once.

Scope

  • Add the four semantic colour triplets to app/themes/light.css and app/themes/dark.css, mirroring the accent shape:
    • --success / --success-subtle / --success-text
    • --warning / --warning-subtle / --warning-text
    • --danger / --danger-subtle / --danger-text
    • --info / --info-subtle / --info-text
      Values lifted from the DS reference if/when the design package surfaces them; otherwise tuned to read on both --surface and --bg in both themes (the dark-mode override values already in the affected components are a reasonable starting point — see the inlined #4ade80 / #fbbf24 / #f87171 / #60a5fa set).
  • Migrate the four affected primitive CSS files off the inlined hex + [data-theme="dark"] blocks:
    • app/components/ui/Badge.module.css.tone-success/-warning/-danger/-info
    • app/components/ui/Field.module.css.required and .error
    • app/components/ui/Input.module.css, Textarea.module.css, Select.module.css — the [aria-invalid="true"] border + ring colours
  • Verify the /dev/components showcase still reads the same in both themes after the migration. The cleanest visual check is a side-by-side before/after of the showcase page.
  • ADR-0023's "Carol DS token migration" already covers the bridge pattern — no new ADR needed; this is just extending the alias set the DS already implies.

Acceptance criteria

  • All four semantic triplets defined in light.css and dark.css.
  • The five primitive .module.css files no longer carry inline hex values or [data-theme="dark"] overrides for the four semantics.
  • /dev/components renders the same in both themes as it does today on the post-#139 baseline.
  • npm run lint, typecheck, build, test all green.
  • If the design package starts including the semantic tokens in ../carol-design/README.md before this lands, use those values verbatim; otherwise the inlined-dark values stay the baseline.

Out of scope

  • Adding semantic tokens for any of the other DS notions that don't have a primitive consumer yet (--brand-purple, --violet-*, etc. — the DS hasn't committed to any of them as named aliases either).
  • Rebuilding the four semantic colours' values. This is a structural migration; the visual surface stays the same as today's post-#139 state.

Part of epic #2. Follow-up from #139 / ADR-0024.

Follow-up from #139 (ADR-0024). The accent semantic in the Carol DS surfaces as a three-token set — `--accent` / `--accent-subtle` / `--accent-text` — that themes override and components consume by name. The four other DS-recognised semantics (success / warning / danger / info) don't have that treatment yet: #139's primitives inline literal hex values for them, with hand-written `[data-theme="dark"]` overrides per component. That's a real ergonomic + correctness gap: - **Drift surface.** Today four files (`Badge.module.css`, `Field.module.css`, `Input.module.css`, `Textarea.module.css`, `Select.module.css`) each carry their own copies of the four semantic colour pairs plus their dark-mode overrides. A future tweak to "the warning amber" has to touch every file or risk a mismatch. - **Pattern mismatch.** The accent flow is the model: components write `var(--accent-subtle)` + `var(--accent-text)` and the theme decides what the actual colour is. The semantics deserve the same shape. - **Theme-switch fragility.** Each `[data-theme="dark"]` override in component CSS is a place future themes (auto, high-contrast, etc.) have to be patched. A token-level definition is patched once. ## Scope - Add the four semantic colour triplets to `app/themes/light.css` and `app/themes/dark.css`, mirroring the accent shape: - `--success` / `--success-subtle` / `--success-text` - `--warning` / `--warning-subtle` / `--warning-text` - `--danger` / `--danger-subtle` / `--danger-text` - `--info` / `--info-subtle` / `--info-text` Values lifted from the DS reference if/when the design package surfaces them; otherwise tuned to read on both `--surface` and `--bg` in both themes (the dark-mode override values already in the affected components are a reasonable starting point — see the inlined `#4ade80` / `#fbbf24` / `#f87171` / `#60a5fa` set). - Migrate the four affected primitive CSS files off the inlined hex + `[data-theme="dark"]` blocks: - `app/components/ui/Badge.module.css` — `.tone-success/-warning/-danger/-info` - `app/components/ui/Field.module.css` — `.required` and `.error` - `app/components/ui/Input.module.css`, `Textarea.module.css`, `Select.module.css` — the `[aria-invalid="true"]` border + ring colours - Verify the `/dev/components` showcase still reads the same in both themes after the migration. The cleanest visual check is a side-by-side before/after of the showcase page. - ADR-0023's "Carol DS token migration" already covers the bridge pattern — no new ADR needed; this is just extending the alias set the DS already implies. ## Acceptance criteria - [ ] All four semantic triplets defined in `light.css` and `dark.css`. - [ ] The five primitive `.module.css` files no longer carry inline hex values or `[data-theme="dark"]` overrides for the four semantics. - [ ] `/dev/components` renders the same in both themes as it does today on the post-#139 baseline. - [ ] `npm run lint`, `typecheck`, `build`, `test` all green. - [ ] If the design package starts including the semantic tokens in `../carol-design/README.md` before this lands, use those values verbatim; otherwise the inlined-dark values stay the baseline. ## Out of scope - Adding semantic tokens for any of the *other* DS notions that don't have a primitive consumer yet (`--brand-purple`, `--violet-*`, etc. — the DS hasn't committed to any of them as named aliases either). - Rebuilding the four semantic colours' values. This is a structural migration; the visual surface stays the same as today's post-#139 state. Part of epic #2. Follow-up from #139 / ADR-0024.
james closed this issue 2026-06-20 14:06:32 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
james/carol#149
No description provided.