Skip to content

feat(theme): migrate UI colors to IO design tokens - #3849

Draft
tegan-temporal wants to merge 40 commits into
mainfrom
color-token-migration
Draft

feat(theme): migrate UI colors to IO design tokens#3849
tegan-temporal wants to merge 40 commits into
mainfrom
color-token-migration

Conversation

@tegan-temporal

@tegan-temporal tegan-temporal commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Description & motivation 💭

Completes the migration from legacy Tailwind color aliases and theme variables to the reconciled IO design-token system.

This PR:

  • adds the Figma-aligned IO primitive, alpha, and semantic color scales
  • exposes only IO colors plus Tailwind's standard inherit, current, and transparent color keywords
  • defines semantic background, surface, content, border, interactive, actions, and overlay token families
  • migrates application and Holocene consumers away from legacy color utilities and variables
  • removes the redundant surface.status.* namespace in favor of canonical semantic surfaces
  • preserves true-alpha overlays where Figma defines compositing behavior
  • uses opaque semantic surfaces for component bodies in both light and dark themes
  • updates categorical timeline/event visualization colors to reference IO primitives instead of embedded literals
  • makes the standalone markdown renderer consume the same semantic color source as the application
  • adds a repository-wide audit that prevents legacy Tailwind colors, legacy component color aliases, and non-IO color variables from returning

Figma sources:

Screenshots (if applicable) 📸

No static screenshots are attached. Affected controls and components can be reviewed in Storybook in both light and dark themes.

Key areas for visual review:

  • Button, Badge, and Chip variants, including counts and active states
  • Input, Number Input, Chip Input, Duration Input, Range Input, and Textarea
  • Checkbox, Toggle Switch, Select, Combobox, and Menu
  • Alerts, execution status, worker status, and saved-view counts
  • Drawer, Tooltip, Code Block, and markdown rendering
  • Event history legend, timeline graph, and workflow-family visualization
  • Empty states that extend the bundled illustration background

Design considerations 🎨

The implementation follows the current Figma distinction between opaque surfaces and true-alpha overlays:

background.primary canvas
└── surface.* opaque component/container body
    └── overlay.* true-alpha nested or composited treatment

Conventions used in this PR:

  • standard focus rings use interactive.primary with the component-appropriate offset
  • validation borders and focus rings use danger semantics
  • hover and pressed treatments use Actions overlays where specified
  • status component bodies use semantic information/success/warning/danger/error surfaces
  • chip count and similar nested treatments use Figma's alpha overlays where compositing is intended
  • categorical chart and graph colors use IO primitives rather than proliferating semantic component tokens
  • cloud-provider and language-logo brand artwork retains its authored colors
  • the custom progress-bar rendering remains an intentional inline-color exception because it has no clear design-token equivalent

The empty-state illustration continuation uses indigo.8: the SVG ground fill and adjacent UI fill now share the same IO primitive so there is no visible seam.

The standalone markdown document cannot inherit application CSS variables, so its server route injects light and dark variables directly from semanticColors before the reset stylesheet.

Testing 🧪

How was this tested 👻

  • Manual review throughout the migration
  • Unit tests
  • Repository-wide legacy-color audit

Latest validation:

pnpm audit:tailwind
pnpm audit:tailwind -- .
pnpm lint
pnpm check
pnpm exec vitest run src/lib/theme/io/semantic-colors.test.ts src/lib/components/lines-and-dots/timeline-graph/timeline-positioning.test.ts src/lib/components/lines-and-dots/timeline-graph/timeline.svelte.test.ts

Results:

  • legacy color audits: passed; no legacy Tailwind colors found in src or the repository
  • lint: 0 errors; 58 existing warnings
  • Svelte/TypeScript check: 0 errors; 118 existing warnings
  • focused tests: 48 passed
  • all edited Svelte components passed the Svelte autofixer
  • git diff --check: passed

Steps for others to test 🚶🏽‍♂️🚶🏽‍♀️

  1. Run Storybook and switch between light and dark themes.
  2. Review the component stories and states listed above.
  3. Exercise default, hover, focus, pressed/open, disabled, selected, invalid, and count states.
  4. Verify the markdown renderer in light, dark, background, and primary variants.
  5. Review event-history and timeline visualization colors for category distinction.
  6. Confirm empty-state illustrations have no seam between the SVG and continuation fill.

Checklists

Migration checklist

  • Remove legacy Tailwind color utilities
  • Remove legacy theme variables and component color aliases
  • Restrict Tailwind colors to IO tokens and standard keywords
  • Align semantic surface, content, border, and overlay values with Figma
  • Remove redundant status-surface aliases
  • Migrate normal UI color literals to semantic tokens
  • Migrate categorical visualization literals to IO primitives
  • Add repository-wide regression audit
  • Complete final source cleanup pass

Review checklist

  • Complete final visual review in Storybook and application pages
  • Confirm light and dark component contrast with Design
  • Add screenshots or recordings if desired before marking ready

Issue(s) closed

None.

Docs

Any docs updates needed?

No external documentation updates are required. The semantic token definitions, focused tests, and legacy-color audit in this PR are the source of truth for the migration.

@vercel

vercel Bot commented Aug 20, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
holocene Ready Ready Preview Aug 21, 2026 7:21pm

Request Review

# Conflicts:
#	src/lib/catalog/browser/catalog-detail.svelte
#	src/lib/catalog/browser/catalog-detail.test.ts
#	src/lib/components/bottom-nav.svelte
#	src/lib/components/command-palette/index.svelte
#	src/lib/components/deployments/set-current-version-modal.svelte
#	src/lib/components/event/pending-nexus-summary-row.svelte
#	src/lib/components/lines-and-dots/workflow-error.svelte
#	src/lib/components/payload/payload-code-block.svelte
#	src/lib/components/schedule/schedule-action-modals/backfill-schedule-modal.svelte
#	src/lib/components/schedule/schedule-form/spec-run-time.svelte
#	src/lib/components/workers/pollers-table/poller-icon.svelte
#	src/lib/components/workers/worker-details/worker-details.svelte
#	src/lib/components/workflow/pending-activity/pending-activity-card.svelte
#	src/lib/components/workflow/pending-nexus-operation/pending-nexus-operation-card.svelte
#	src/lib/holocene/combobox/combobox.stories.svelte
#	src/lib/holocene/drawer.svelte
#	src/lib/pages/standalone-activity-details.svelte
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