feat(eslint): forbid hardcoded hex colors in apps/web (Sprint 2 follow-up #3)

Add no-restricted-syntax rule matching string literals of form #RGB / #RRGGBB /
#RRGGBBAA. Catches hex colors anywhere in JS/TS — JSX inline styles, template
literals, prop defaults, config arrays, etc.

Message points users to the right escape hatch:
- var(--sumi-*) for CSS contexts (JSX style/className, template literals)
- import {ColorVizIndigo, ...} from '@veza/design-system/tokens-generated' for
  canvas/runtime contexts where var() can't resolve.

Single source of truth: packages/design-system/tokens/primitive/color.json.

Severity: warn (not error) — gives a smooth migration ramp; can be flipped to
error in a future sprint once the 3 PieChart pigment TODOs (sakura, terminal,
magenta) are canonized in tokens.

The rule will catch any new hex regression at lint time, completing the
"single source of truth" guarantee started by Style Dictionary in Sprint 2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
senke 2026-04-27 16:44:58 +02:00
parent f46d5ead6f
commit b4710909c0

View file

@ -225,6 +225,17 @@ export default [js.configs.recommended, {
message: message:
'Use SUMI design system semantic tokens (primary, secondary, destructive, success, warning, muted, foreground, etc.) instead of Tailwind default colors. See apps/web/docs/DESIGN_TOKENS.md for token mapping. For exceptions (e.g., test files), add eslint-disable comment.', 'Use SUMI design system semantic tokens (primary, secondary, destructive, success, warning, muted, foreground, etc.) instead of Tailwind default colors. See apps/web/docs/DESIGN_TOKENS.md for token mapping. For exceptions (e.g., test files), add eslint-disable comment.',
}, },
// Hex colors: Prevent literal hex colors in JS/TS strings (use tokens instead).
// Matches strings like '#7c9dd6', '#fff', '#0d0d0fAA' — anywhere in code.
// Use var(--sumi-*) in CSS contexts (JSX style props, template literals)
// OR import { ColorXxx } from '@veza/design-system/tokens-generated' for canvas/runtime.
// Exceptions: rgba()/hsla() (not # prefix), the design-system package itself (different rule scope).
{
selector:
"Literal[value=/^#[0-9a-fA-F]{3,8}$/]",
message:
'Hardcoded hex color literal. Use SUMI tokens: var(--sumi-*) for CSS strings (JSX style/className), or import {ColorVizIndigo, ColorMizuBase, ...} from \'@veza/design-system/tokens-generated\' for canvas/runtime contexts. Source of truth: packages/design-system/tokens/primitive/color.json. See CHARTE_GRAPHIQUE_TALAS.md §4.',
},
// Components: Enforce Button component usage (prevent native button elements) // Components: Enforce Button component usage (prevent native button elements)
// Warn on native <button> elements - use <Button> component from @/components/ui/button instead // Warn on native <button> elements - use <Button> component from @/components/ui/button instead
{ {