Skip to main content

Source: ocean/docs/adr/0027-palettes-canonical-source-and-semantic-color-lint.md | ✏️ Edit on GitHub

ADR-0027: Canonical Palettes Source + Semantic Color Enforcement

Date: 2025-08-14

Status

Accepted

Context

We adopted a token-driven design pipeline (ADR-0025) and added CI validation (ADR-0026). To fully eliminate design drift and ensure maintainability with Tailwind 4 + shadcn, we need a single canonical palettes source and enforcement against raw Tailwind color utilities.

Decision

  • Make design-tokens/palettes.json the single source of truth for color palettes (light/dark for each palette).
  • Generate both runtime artifacts from this source:
    • src/styles/color-themes.generated.css (Style Dictionary)
    • src/config/themes.ts (script) for app-level palette metadata
  • Add derived status tokens mapped to current palette for non-disruptive migration:
    • --success, --warning, --info, --negative (+ *-muted)
  • Enforce semantic colors via ESLint rule ocean/no-raw-colors which forbids raw Tailwind color utilities (e.g., text-green-600) and requires semantic utilities (e.g., text-success, bg-background).
  • Pre-commit hook runs: tokens build → themes generation → design validation when design files change.

Consequences

  • Pros
    • One canonical definition for palettes; prevents drift between code and CSS output
    • Automated generation keeps shadcn semantics consistent across the app
    • Lint rule blocks regressions and ensures long-term maintainability
    • Status tokens preserve existing visual intent while aligning to tokens
  • Cons
    • Requires updating custom colors to semantic utilities (initial migration done)
    • Contributors must follow semantic color usage (lint enforced)

Implementation

  • Sources
    • design-tokens/palettes.json (canonical palettes; includes optional name/description)
  • Build & Validation
    • style-dictionary.config.js → emits src/styles/color-themes.generated.css
    • tools/generate-themes-ts.js → emits src/config/themes.ts from palettes
    • tools/validate-design.js → compares generated CSS to palettes.json
    • package.json scripts: tokens:build, tokens:themes, design:validate
    • .husky/pre-commit runs build + generation + validation for relevant changes
  • Enforcement
    • eslint.config.js includes inline plugin rule ocean/no-raw-colors
    • Allowed semantic utilities include: background/foreground/card/... and status: success, warning, info, negative (+ -muted)
    • tools/codemod-replace-raw-colors.ts assists migration

Rollback Plan

  • Disable the ESLint rule if blocking issues occur; runtime remains token-driven
  • Revert themes.ts generation and keep only CSS generation if necessary

References

  • ADR-0025: Token-driven Design System with Tailwind 4 and shadcn
  • ADR-0026: Enforce Design Token Validation in CI