From b4710909c0e3772f438f7a4477ab5116c2ceb156 Mon Sep 17 00:00:00 2001 From: senke Date: Mon, 27 Apr 2026 16:44:58 +0200 Subject: [PATCH] feat(eslint): forbid hardcoded hex colors in apps/web (Sprint 2 follow-up #3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- apps/web/eslint.config.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/apps/web/eslint.config.js b/apps/web/eslint.config.js index 1b69e1d8c..d6c10df4f 100644 --- a/apps/web/eslint.config.js +++ b/apps/web/eslint.config.js @@ -225,6 +225,17 @@ export default [js.configs.recommended, { 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.', }, + // 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) // Warn on native