refactor(design-system): finish Sprint 2 — light theme + 3 viz pigments canonized

Closes Sprint 2 100%. The drift is fully eliminated.

Light theme migration :
- packages/design-system/tokens/semantic/light.json now exhaustively mirrors
  the former apps/web/src/index.css [data-theme="light"] block byte-for-byte
  (~50 tuned values: bg/surface/border/text/accent/error/sage/gold/kin/live/
  shadow/glass/scrollbar/grain-opacity).
- apps/web/src/index.css [data-theme="light"] block reduced from 70 LOC to 5
  (only --primary-foreground shadcn override remains). 1398 -> 1334 LOC total.

3 viz pigments canonized :
- packages/design-system/tokens/primitive/color.json : added viz.sakura
  (#e0a0b8), viz.terminal (#3eaa5e), viz.magenta (#c840a0). Now 8 pigments
  total (5 principaux + 3 extras for charts >5 series).
- semantic/dark.json : sumi.viz exposes the 3 new pigments as well.
- components/charts/PieChart.tsx : DEFAULT_COLORS[5..7] now use
  var(--sumi-viz-{sakura,terminal,magenta}) — all hex literals eliminated.
  ESLint hex-color rule clean on this file.

Build OK (vite 13.3s). All --sumi-* aliases now sourced from tokens.css.
The only --sumi-* defined in index.css are app-specific shadcn shims
(--background, --foreground, etc. mapping shadcn vars to --sumi-*) and
runtime state (--sumi-patina-warmth, --sumi-grain-opacity for dark base).

Sprint 2 metrics : 32 -> 0 hex literals in apps/web/src.
Single source of truth = packages/design-system/tokens/*.json.
ESLint guardrail enforces it for new code.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
senke 2026-04-27 16:57:12 +02:00
parent 17cafbaa71
commit cb511afa6e
5 changed files with 81 additions and 113 deletions

View file

@ -16,17 +16,16 @@ export interface PieChartProps extends Omit<ChartProps, 'children'> {
}
// Data viz pigments — see CHARTE_GRAPHIQUE_TALAS §4.5 (data viz only).
// First 5 are canonical; sakura/terminal/magenta are app-specific extras pending
// canonical definition in tokens (follow-up Sprint 2).
// 5 principaux + 3 extras pour charts >5 séries.
const DEFAULT_COLORS = [
'var(--sumi-viz-indigo)',
'var(--sumi-viz-vermillion)',
'var(--sumi-viz-sage)',
'var(--sumi-viz-gold)',
'var(--sumi-viz-neutral)',
'#e0a0b8', // sakura — TODO: canonize in tokens/primitive/color.json viz palette
'#3eaa5e', // terminal-green — TODO: canonize
'#c840a0', // graffiti-magenta — TODO: canonize
'var(--sumi-viz-sakura)',
'var(--sumi-viz-terminal)',
'var(--sumi-viz-magenta)',
];
/**

View file

@ -257,73 +257,9 @@
LIGHT THEME Washi Paper (和紙) Ink on warm paper
*/
[data-theme="light"] {
--sumi-bg-void: #E8E3DB;
--sumi-bg-base: #F2EDE6;
--sumi-bg-raised: #F2EDE6;
--sumi-bg-overlay: #F2EDE6;
--sumi-bg-hover: #E8E3DB;
--sumi-bg-active: #DED9D1;
--sumi-bg-wash: #ECE7DF;
--sumi-surface-inset: #E0DBD3;
--sumi-surface-subtle: #E8E3DB;
--sumi-surface-card: #F2EDE6;
--sumi-surface-elevated: #F7F2EB;
--sumi-border-faint: rgba(26,26,30, 0.04);
--sumi-border-default: rgba(26,26,30, 0.06);
--sumi-border-strong: rgba(26,26,30, 0.12);
--sumi-border-focus: rgba(0,122,148, 0.45);
--sumi-border-accent: rgba(0,122,148, 0.20);
--sumi-text-primary: #1A1A1E;
--sumi-text-secondary: #4A4A50;
--sumi-text-tertiary: #6B6660;
--sumi-text-disabled: #B5B0A8;
--sumi-text-inverse: #E8E3DB;
--sumi-text-link: #006B7F;
--sumi-accent: #007A94;
--sumi-accent-hover: #006B7F;
--sumi-accent-active: #008DAD;
--sumi-accent-subtle: rgba(0,122,148, 0.08);
--sumi-accent-muted: rgba(0,122,148, 0.15);
--sumi-accent-emphasis: #005A6B;
--sumi-error: rgba(180,80,70, 0.70);
--sumi-error-hover: rgba(180,80,70, 0.80);
--sumi-error-subtle: rgba(180,80,70, 0.08);
--sumi-sage: rgba(60,100,70, 0.75);
--sumi-sage-hover: rgba(60,100,70, 0.85);
--sumi-sage-subtle: rgba(60,100,70, 0.08);
--sumi-gold: rgba(160,125,40, 0.70);
--sumi-gold-hover: rgba(160,125,40, 0.80);
--sumi-gold-subtle: rgba(160,125,40, 0.08);
--sumi-kin: #9a7208;
--sumi-kin-hover: #886008;
--sumi-kin-subtle: rgba(154,114,8, 0.06);
--sumi-live: rgba(180,80,70, 0.70);
--sumi-shadow-xs: 0 0 4px rgba(26,26,30, 0.03);
--sumi-shadow-sm: 0 0 8px rgba(26,26,30, 0.04);
--sumi-shadow-md: 0 0 16px rgba(26,26,30, 0.06);
--sumi-shadow-lg: 0 0 24px rgba(26,26,30, 0.08);
--sumi-shadow-xl: 0 0 32px rgba(26,26,30, 0.10);
--sumi-shadow-2xl: 0 0 48px rgba(26,26,30, 0.12);
--sumi-shadow-glow: 0 0 0 3px rgba(0,122,148, 0.18);
--sumi-shadow-kin: 0 0 16px rgba(154,114,8, 0.12);
--sumi-glass-bg: rgba(242,237,230, 0.85);
--sumi-glass-border: rgba(26,26,30, 0.04);
--sumi-scrollbar-thumb: rgba(26,26,30, 0.08);
--sumi-scrollbar-hover: rgba(26,26,30, 0.16);
/* --sumi-grain-opacity overridden via tokens-light.css (see semantic/light.json) */
/* All --sumi-* light theme overrides tokenized in @veza/design-system/tokens.css
(see semantic/light.json byte-for-byte preservation of former tuned values).
This block keeps only app-specific shadcn/Radix overrides for light theme. */
--primary-foreground: #F2EDE6;
}

View file

@ -57,12 +57,15 @@
"sakura": { "$value": "#d4a0b0", "$type": "color" }
},
"viz": {
"_comment": "Data viz palette ONLY (charts, waveforms, analytics). Forbidden in standard UI per CHARTE_GRAPHIQUE_TALAS §4.5",
"indigo": { "$value": "#7c9dd6", "$type": "color", "$description": "Data viz pigment — indigo" },
"vermillion": { "$value": "#d4634a", "$type": "color", "$description": "Data viz pigment — vermillion" },
"sage": { "$value": "#7a9e6c", "$type": "color", "$description": "Data viz pigment — sage" },
"gold": { "$value": "#c9a84c", "$type": "color", "$description": "Data viz pigment — gold" },
"neutral": { "$value": "#a8a4a0", "$type": "color", "$description": "Data viz pigment — neutral grey" }
"_comment": "Data viz palette ONLY (charts, waveforms, analytics). Forbidden in standard UI per CHARTE_GRAPHIQUE_TALAS §4.5. 5 pigments principaux + 3 extras pour graphes >5 séries.",
"indigo": { "$value": "#7c9dd6", "$type": "color", "$description": "Data viz pigment — indigo (principal #1)" },
"vermillion": { "$value": "#d4634a", "$type": "color", "$description": "Data viz pigment — vermillion (principal #2)" },
"sage": { "$value": "#7a9e6c", "$type": "color", "$description": "Data viz pigment — sage (principal #3)" },
"gold": { "$value": "#c9a84c", "$type": "color", "$description": "Data viz pigment — gold (principal #4)" },
"neutral": { "$value": "#a8a4a0", "$type": "color", "$description": "Data viz pigment — neutral grey (principal #5)" },
"sakura": { "$value": "#e0a0b8", "$type": "color", "$description": "Data viz pigment — sakura pink (extra, charts >5 séries)" },
"terminal": { "$value": "#3eaa5e", "$type": "color", "$description": "Data viz pigment — terminal green (extra, charts >5 séries)" },
"magenta": { "$value": "#c840a0", "$type": "color", "$description": "Data viz pigment — graffiti magenta (extra, charts >5 séries)" }
},
"functional": {
"_comment": "Functional colors are ALWAYS diluted (max 60% opacity). Never as solid fill (charte §4.2)",

View file

@ -25,12 +25,15 @@
"accent": { "$value": "{color.mizu.border}", "$type": "color" }
},
"viz": {
"_comment": "Data viz uniquement (charts, waveforms, analytics) — charte §4.5",
"_comment": "Data viz uniquement (charts, waveforms, analytics) — charte §4.5. Principaux + extras.",
"indigo": { "$value": "{color.viz.indigo}", "$type": "color" },
"vermillion": { "$value": "{color.viz.vermillion}", "$type": "color" },
"sage": { "$value": "{color.viz.sage}", "$type": "color" },
"gold": { "$value": "{color.viz.gold}", "$type": "color" },
"neutral": { "$value": "{color.viz.neutral}", "$type": "color" }
"neutral": { "$value": "{color.viz.neutral}", "$type": "color" },
"sakura": { "$value": "{color.viz.sakura}", "$type": "color" },
"terminal": { "$value": "{color.viz.terminal}", "$type": "color" },
"magenta": { "$value": "{color.viz.magenta}", "$type": "color" }
},
"ink": {
"_comment": "墨の六色 — Six tones of ink (theme-independent backward-compat aliases)",

View file

@ -1,49 +1,76 @@
{
"sumi": {
"_comment": "Light theme overrides — washi paper aesthetic ([data-theme=\"light\"]). Only theme-DEPENDENT tokens; the rest inherits from dark.json :root selector.",
"_comment": "Light theme overrides — washi paper aesthetic ([data-theme=\"light\"]). Theme-tuned hex/opacity values (preserved byte-for-byte from former apps/web/src/index.css [data-theme=\"light\"] block). The rest inherits from dark.json :root selector.",
"bg": {
"void": { "$value": "{color.washi.shiro}", "$type": "color" },
"base": { "$value": "{color.washi.shiro}", "$type": "color" },
"raised": { "$value": "{color.washi.shiro}", "$type": "color" },
"overlay": { "$value": "{color.washi.kinari}", "$type": "color" },
"hover": { "$value": "{color.washi.kinari}", "$type": "color" },
"active": { "$value": "{color.washi.kinu}", "$type": "color" },
"wash": { "$value": "{color.washi.kinari}", "$type": "color" }
"void": { "$value": "#E8E3DB", "$type": "color" },
"base": { "$value": "#F2EDE6", "$type": "color" },
"raised": { "$value": "#F2EDE6", "$type": "color" },
"overlay": { "$value": "#F2EDE6", "$type": "color" },
"hover": { "$value": "#E8E3DB", "$type": "color" },
"active": { "$value": "#DED9D1", "$type": "color" },
"wash": { "$value": "#ECE7DF", "$type": "color" }
},
"surface": {
"inset": { "$value": "{color.washi.kinari}", "$type": "color" },
"subtle": { "$value": "{color.washi.shiro}", "$type": "color" },
"card": { "$value": "{color.washi.shiro}", "$type": "color" },
"elevated": { "$value": "{color.washi.shiro}", "$type": "color" }
"inset": { "$value": "#E0DBD3", "$type": "color" },
"subtle": { "$value": "#E8E3DB", "$type": "color" },
"card": { "$value": "#F2EDE6", "$type": "color" },
"elevated": { "$value": "#F7F2EB", "$type": "color" }
},
"border": {
"faint": { "$value": "{color.alpha.ink-04}", "$type": "color" },
"default": { "$value": "{color.alpha.ink-06}", "$type": "color" },
"strong": { "$value": "{color.alpha.ink-12}", "$type": "color" },
"focus": { "$value": "{color.mizu.focus}", "$type": "color" },
"accent": { "$value": "{color.mizu.border}", "$type": "color" }
"faint": { "$value": "rgba(26,26,30, 0.04)", "$type": "color" },
"default": { "$value": "rgba(26,26,30, 0.06)", "$type": "color" },
"strong": { "$value": "rgba(26,26,30, 0.12)", "$type": "color" },
"focus": { "$value": "rgba(0,122,148, 0.45)", "$type": "color" },
"accent": { "$value": "rgba(0,122,148, 0.20)", "$type": "color" }
},
"text-primary": { "$value": "{color.ink.sumi}", "$type": "color" },
"text-secondary": { "$value": "{color.ink.gin}", "$type": "color" },
"text-tertiary": { "$value": "{color.ink.hai}", "$type": "color" },
"text-disabled": { "$value": "{color.ink.kasumi}", "$type": "color" },
"text-inverse": { "$value": "{color.washi.kinari}", "$type": "color" },
"text-link": { "$value": "{color.mizu.deep}", "$type": "color", "$description": "Cyan profond pour AA en mode jour" },
"text-primary": { "$value": "#1A1A1E", "$type": "color" },
"text-secondary": { "$value": "#4A4A50", "$type": "color" },
"text-tertiary": { "$value": "#6B6660", "$type": "color" },
"text-disabled": { "$value": "#B5B0A8", "$type": "color" },
"text-inverse": { "$value": "#E8E3DB", "$type": "color" },
"text-link": { "$value": "#006B7F", "$type": "color" },
"accent": { "$value": "{color.mizu.base}", "$type": "color" },
"accent-hover": { "$value": "{color.mizu.active}", "$type": "color" },
"accent-active": { "$value": "{color.mizu.deep}", "$type": "color" },
"accent-muted": { "$value": "{color.mizu.muted}", "$type": "color" },
"accent-subtle": { "$value": "{color.mizu.subtle}", "$type": "color" },
"accent-emphasis": { "$value": "{color.mizu.deep}", "$type": "color" },
"accent": { "$value": "#007A94", "$type": "color" },
"accent-hover": { "$value": "#006B7F", "$type": "color" },
"accent-active": { "$value": "#008DAD", "$type": "color" },
"accent-subtle": { "$value": "rgba(0,122,148, 0.08)", "$type": "color" },
"accent-muted": { "$value": "rgba(0,122,148, 0.15)", "$type": "color" },
"accent-emphasis": { "$value": "#005A6B", "$type": "color" },
"glass-bg": { "$value": "rgba(242,237,230, 0.85)", "$type": "color", "$description": "Shoji screen — light theme washi" },
"glass-border": { "$value": "{color.alpha.ink-04}", "$type": "color" },
"error": { "$value": "rgba(180,80,70, 0.70)", "$type": "color" },
"error-hover": { "$value": "rgba(180,80,70, 0.80)", "$type": "color" },
"error-subtle": { "$value": "rgba(180,80,70, 0.08)", "$type": "color" },
"scrollbar-thumb": { "$value": "{color.alpha.ink-08}", "$type": "color" },
"scrollbar-hover": { "$value": "{color.alpha.ink-12}", "$type": "color" },
"sage": { "$value": "rgba(60,100,70, 0.75)", "$type": "color" },
"sage-hover": { "$value": "rgba(60,100,70, 0.85)", "$type": "color" },
"sage-subtle": { "$value": "rgba(60,100,70, 0.08)", "$type": "color" },
"gold": { "$value": "rgba(160,125,40, 0.70)", "$type": "color" },
"gold-hover": { "$value": "rgba(160,125,40, 0.80)", "$type": "color" },
"gold-subtle": { "$value": "rgba(160,125,40, 0.08)", "$type": "color" },
"kin": { "$value": "#9a7208", "$type": "color" },
"kin-hover": { "$value": "#886008", "$type": "color" },
"kin-subtle": { "$value": "rgba(154,114,8, 0.06)", "$type": "color" },
"live": { "$value": "rgba(180,80,70, 0.70)", "$type": "color" },
"shadow-xs": { "$value": "0 0 4px rgba(26,26,30, 0.03)", "$type": "shadow" },
"shadow-sm": { "$value": "0 0 8px rgba(26,26,30, 0.04)", "$type": "shadow" },
"shadow-md": { "$value": "0 0 16px rgba(26,26,30, 0.06)", "$type": "shadow" },
"shadow-lg": { "$value": "0 0 24px rgba(26,26,30, 0.08)", "$type": "shadow" },
"shadow-xl": { "$value": "0 0 32px rgba(26,26,30, 0.10)", "$type": "shadow" },
"shadow-2xl": { "$value": "0 0 48px rgba(26,26,30, 0.12)", "$type": "shadow" },
"shadow-glow": { "$value": "0 0 0 3px rgba(0,122,148, 0.18)", "$type": "shadow" },
"shadow-kin": { "$value": "0 0 16px rgba(154,114,8, 0.12)", "$type": "shadow" },
"glass-bg": { "$value": "rgba(242,237,230, 0.85)", "$type": "color" },
"glass-border": { "$value": "rgba(26,26,30, 0.04)", "$type": "color" },
"scrollbar-thumb": { "$value": "rgba(26,26,30, 0.08)", "$type": "color" },
"scrollbar-hover": { "$value": "rgba(26,26,30, 0.16)", "$type": "color" },
"grain-opacity": { "$value": "0.06", "$type": "number", "$description": "Grain plus prononcé sur papier washi" }
}