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.jsonthe 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-colorswhich 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→ emitssrc/styles/color-themes.generated.csstools/generate-themes-ts.js→ emitssrc/config/themes.tsfrom palettestools/validate-design.js→ compares generated CSS topalettes.jsonpackage.jsonscripts:tokens:build,tokens:themes,design:validate.husky/pre-commitruns build + generation + validation for relevant changes
- Enforcement
eslint.config.jsincludes inline plugin ruleocean/no-raw-colors- Allowed semantic utilities include: background/foreground/card/... and status: success, warning, info, negative (+ -muted)
tools/codemod-replace-raw-colors.tsassists migration
Rollback Plan
- Disable the ESLint rule if blocking issues occur; runtime remains token-driven
- Revert
themes.tsgeneration 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