refactor: Phase 8 — Update docs, ESLint, Storybook config for SUMI

- DESIGN_TOKENS.md: Complete rewrite to document --sumi-* token system
- APP_SHELL.md: Update layout shell docs (glass bg, backdrop-blur, z-index)
- DESIGN_DIRECTION.md: Update aesthetic direction to SUMI philosophy
- .storybook/preview.tsx: Remove deleted CSS imports, update bg colors
- eslint.config.js: Update color rule message from Kodo to SUMI tokens
- tailwind.config.ts: Fix comment referencing deleted design-tokens.css

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
senke 2026-02-12 02:15:11 +01:00
parent 73e8372b0e
commit 34e1f41091
6 changed files with 555 additions and 436 deletions

View file

@ -7,9 +7,6 @@ import type { Preview } from '@storybook/react';
import { initialize, mswLoader } from 'msw-storybook-addon'; import { initialize, mswLoader } from 'msw-storybook-addon';
import { handlers } from '../src/mocks/handlers'; import { handlers } from '../src/mocks/handlers';
import '../src/index.css'; import '../src/index.css';
import '../src/styles/design-system.css';
import '../src/styles/global-effects.css';
import '../src/styles/header.css';
import '../src/lib/i18n'; // Initialize i18n import '../src/lib/i18n'; // Initialize i18n
import React from 'react'; import React from 'react';
import { StorybookDecorator } from './decorators'; import { StorybookDecorator } from './decorators';
@ -68,9 +65,9 @@ const preview: Preview = {
backgrounds: { backgrounds: {
default: 'dark', default: 'dark',
values: [ values: [
{ name: 'dark', value: '#121212' }, { name: 'dark', value: '#121215' },
{ name: 'light', value: '#ffffff' }, { name: 'light', value: '#faf9f6' },
{ name: 'steel', value: '#1a1a2e' }, { name: 'raised', value: '#1a1a1f' },
], ],
}, },
layout: 'centered', layout: 'centered',

View file

@ -1,28 +1,59 @@
# App Shell — Référence # App Shell — Référence (SUMI)
Vue densemble du shell applicatif (layout principal) et des tokens CSS associés. Toute évolution du shell (sidebar, header, main, player) doit sappuyer sur ces variables et classes pour rester cohérente. Vue d'ensemble du shell applicatif (layout principal) et des tokens CSS SUMI associés. Toute évolution du shell (sidebar, header, main, player) doit s'appuyer sur ces variables et classes pour rester cohérente.
Source de vérité : [index.css](../src/index.css) — sections "LAYOUT", "GLASS", "Z-INDEX" et les classes utilitaires `@utility`.
## Rôle du shell ## Rôle du shell
- **Sidebar** : navigation fixe à gauche (largeur pilotée par `--sidebar-width-expanded` / `--sidebar-width-collapsed`). Voir [index.css](../src/index.css) section "Sidebar layout". - **Header** : barre fixe en haut (hauteur `--header-height`). Fond **glass** (`--sumi-glass-bg`), `backdrop-blur-[12px]` (`--sumi-glass-blur`), bordure basse `--sumi-border-faint`, z-index **200** (`--sumi-z-sticky`). Le bord gauche suit la sidebar (expanded/collapsed).
- **Header** : barre fixe en haut (hauteur `--header-height`), dont le bord gauche suit la sidebar (expanded/collapsed). - **Sidebar** : navigation fixe à gauche (largeur `--sidebar-width-expanded` / `--sidebar-width-collapsed`). Fond `--sumi-bg-raised`, bordure droite `--sumi-border-faint`. Voir [index.css](../src/index.css) section "Sidebar layout" et le mapping Shadcn `--sidebar-*`.
- **Main** : zone scrollable (contenu des pages). Marges gauche pilotées par létat de la sidebar ; padding top/bottom pour ne pas passer sous le header ni le player. - **Main** : zone scrollable (contenu des pages). Marges gauche pilotées par l'état de la sidebar ; padding top/bottom pour ne pas passer sous le header ni le player. Espacement interne via tokens SUMI (`--sumi-space-*`).
- **Player** : barre de lecture fixe en bas (rendue par `GlobalPlayer` dans `DashboardLayout`). - **Player** : barre de lecture fixe en bas (rendue par `GlobalPlayer` dans `DashboardLayout`). Fond **glass** (`--sumi-glass-bg`), `backdrop-blur-[16px]`, bordure `--sumi-glass-border`, z-index **200** (`--sumi-z-sticky`). Conteneur : `PlayerBarGlass`.
Fichiers principaux : Fichiers principaux :
- [DashboardLayout.tsx](../src/components/layout/DashboardLayout.tsx) — assemblage Sidebar, zone main, Header, GlobalPlayer. - [DashboardLayout.tsx](../src/components/layout/DashboardLayout.tsx) — assemblage Sidebar, zone main, Header, GlobalPlayer.
- [Header.tsx](../src/components/layout/Header.tsx) — barre supérieure (recherche, actions, user menu). - [Header.tsx](../src/components/layout/Header.tsx) — barre supérieure (glass bg, recherche, actions, user menu).
- [PlayerBarGlass.tsx](../src/features/player/components/player-bar/PlayerBarGlass.tsx) — conteneur glassmorphism du player.
## Variables CSS (shell) ## Thème et switching
Définies dans `:root` dans [index.css](../src/index.css), section "App shell" : Le thème est piloté par l'attribut **`[data-theme]`** sur `<html>`, et non par un toggle de classe (`dark`/`light`).
- `ThemeProvider` (`src/components/theme/ThemeProvider.tsx`) pose `data-theme="dark"` ou `data-theme="light"` sur `document.documentElement`.
- Les tokens CSS sont définis dans `:root, [data-theme="dark"]` (dark par défaut) et `[data-theme="light"]` (light theme — Washi Paper).
- Le mode `system` écoute `prefers-color-scheme` et pose le `data-theme` correspondant.
## Variables CSS (shell — SUMI)
### Tokens SUMI globaux (utilisés par le shell)
Définis dans `:root` dans [index.css](../src/index.css) :
| Variable | Valeur (dark) | Rôle |
|----------|---------------|------|
| `--sumi-glass-bg` | `rgba(18,18,21, 0.80)` | Fond glass (header, player) |
| `--sumi-glass-border` | `rgba(255,255,255, 0.08)` | Bordure glass |
| `--sumi-glass-blur` | `12px` | Flou glass (header) |
| `--sumi-bg-raised` | `#1a1a1f` | Fond sidebar |
| `--sumi-border-faint` | `rgba(255,255,255, 0.06)` | Bordure fine (sidebar, header) |
| `--sumi-z-sticky` | `200` | Z-index header et player |
| `--sumi-z-raised` | `10` | Z-index contenu principal |
| `--sumi-header-height` | `56px` | Hauteur header (token SUMI) |
| `--sumi-sidebar-width` | `240px` | Largeur sidebar ouverte (token SUMI) |
| `--sumi-sidebar-collapsed` | `64px` | Largeur sidebar fermée (token SUMI) |
| `--sumi-player-height` | `80px` | Hauteur player bar (token SUMI) |
### Tokens layout du shell (classes utilitaires)
Définis dans la section "App shell" de [index.css](../src/index.css) :
| Variable | Valeur | Rôle | | Variable | Valeur | Rôle |
|----------|--------|------| |----------|--------|------|
| `--header-height` | 4rem | Hauteur de la barre header fixe | | `--header-height` | 4rem | Hauteur de la barre header fixe |
| `--main-offset-top` | 5rem | Padding-top du `<main>` (dégager le header) | | `--main-offset-top` | 5rem | Padding-top du `<main>` (dégager le header) |
| `--main-offset-bottom` | 8rem | Padding-bottom du `<main>` (réserve pour le player) | | `--main-offset-bottom` | 9rem | Padding-bottom du `<main>` (réserve pour le player) |
| `--main-margin-left-expanded` | 18rem | Marge gauche du conteneur main quand sidebar ouverte (15rem sidebar + 3rem gap) | | `--main-margin-left-expanded` | 18rem | Marge gauche du conteneur main quand sidebar ouverte (15rem sidebar + 3rem gap) |
| `--main-margin-left-collapsed` | 7rem | Marge gauche du main quand sidebar fermée (5rem + 2rem gap) | | `--main-margin-left-collapsed` | 7rem | Marge gauche du main quand sidebar fermée (5rem + 2rem gap) |
| `--header-left-expanded` | 18rem | Position `left` de la barre header quand sidebar ouverte | | `--header-left-expanded` | 18rem | Position `left` de la barre header quand sidebar ouverte |
@ -32,7 +63,7 @@ Les largeurs sidebar sont définies à part : `--sidebar-width-expanded` (15rem)
## Classes utilitaires (shell) ## Classes utilitaires (shell)
Définies dans [index.css](../src/index.css) après les classes sidebar (`.left-sidebar`, `.z-sidebar`, etc.) : Définies dans [index.css](../src/index.css) via `@utility` :
| Classe | Propriété | Usage | | Classe | Propriété | Usage |
|--------|-----------|--------| |--------|-----------|--------|
@ -43,9 +74,50 @@ Définies dans [index.css](../src/index.css) après les classes sidebar (`.left-
| `.ml-main-collapsed` | margin-left | Conteneur principal (avec `lg:`) quand sidebar fermée | | `.ml-main-collapsed` | margin-left | Conteneur principal (avec `lg:`) quand sidebar fermée |
| `.left-header-expanded` | left | Barre header quand sidebar ouverte | | `.left-header-expanded` | left | Barre header quand sidebar ouverte |
| `.left-header-collapsed` | left | Barre header quand sidebar fermée | | `.left-header-collapsed` | left | Barre header quand sidebar fermée |
| `.max-w-layout-content` | max-width | Wrapper contenu principal (limite à `--layout-content-max-width`) |
À utiliser avec le préfixe responsive `lg:` pour les marges/positions desktop (ex. `lg:ml-main-expanded`). En dessous de `lg`, la sidebar est en overlay et le main utilise `ml-0`, le header `left-0` (`max-lg:left-0`). À utiliser avec le préfixe responsive `lg:` pour les marges/positions desktop (ex. `lg:ml-main-expanded`). En dessous de `lg`, la sidebar est en overlay et le main utilise `ml-0`, le header `left-0` (`max-lg:left-0`).
## Apparence des zones du shell
### Header
```
bg: var(--sumi-glass-bg) → rgba(18,18,21, 0.80)
blur: backdrop-blur-[12px] → var(--sumi-glass-blur)
border: border-b border-[var(--sumi-border-faint)]
z-index: z-[200] → var(--sumi-z-sticky)
height: h-header → var(--header-height) = 4rem
```
### Sidebar
```
bg: var(--sumi-bg-raised) → #1a1a1f (dark) / #ffffff (light)
border: border-r border-[var(--sumi-border-faint)]
z-index: var(--sidebar-z-index) → 95
width: w-sidebar-expanded (15rem) / w-sidebar-collapsed (5rem)
```
### Player bar
```
bg: var(--sumi-glass-bg) → rgba(18,18,21, 0.80)
blur: backdrop-blur-[16px] → plus prononcé que le header
border: border border-[var(--sumi-glass-border)]
z-index: z-[200] → var(--sumi-z-sticky)
shadow: var(--sumi-shadow-lg) / var(--sumi-shadow-xl) au hover
```
### Main content
```
padding: pt-main (5rem top), pb-main (9rem bottom), px-4 md:px-8
margin: lg:ml-main-expanded / lg:ml-main-collapsed
wrapper: max-w-layout-content mx-auto → limité à var(--layout-content-max-width) = 100rem
scroll: overflow-y-auto custom-scrollbar
```
## Comportement responsive ## Comportement responsive
- **lg (1024px et plus)** : sidebar fixe à gauche, main et header utilisent les classes tokenisées (expanded/collapsed selon `sidebarOpen`). - **lg (1024px et plus)** : sidebar fixe à gauche, main et header utilisent les classes tokenisées (expanded/collapsed selon `sidebarOpen`).
@ -56,7 +128,7 @@ Définies dans [index.css](../src/index.css) après les classes sidebar (`.left-
| Breakpoint | Largeur | Comportement attendu | | Breakpoint | Largeur | Comportement attendu |
|------------|---------|----------------------| |------------|---------|----------------------|
| Mobile | 320px | Sidebar overlay, main pleine largeur, header pleine largeur. | | Mobile | 320px | Sidebar overlay, main pleine largeur, header pleine largeur. |
| Tablet | 768px | Idem (sidebar overlay jusquà lg). | | Tablet | 768px | Idem (sidebar overlay jusqu'à lg). |
| Desktop | 1024px (lg) | Sidebar fixe, main et header avec marges/positions tokenisées. | | Desktop | 1024px (lg) | Sidebar fixe, main et header avec marges/positions tokenisées. |
| Large desktop | 1280px | Même comportement que lg, contenu limité par `max-w-layout-content` si applicable. | | Large desktop | 1280px | Même comportement que lg, contenu limité par `max-w-layout-content` si applicable. |
@ -64,5 +136,8 @@ Vérifier visuellement (ou via tests Playwright) que Sidebar, Header et Main se
## Référence croisée ## Référence croisée
- Tokens SUMI complets (backgrounds, borders, text, glass, shadows, z-index, spacing, radius, motion) : [index.css](../src/index.css) — `:root` et `[data-theme="light"]`.
- Tokens sidebar (largeurs, offsets, z-index) : [index.css](../src/index.css) — "Sidebar layout" et classes `.w-sidebar-expanded`, `.left-sidebar`, `.top-sidebar`, `.bottom-sidebar`, `.z-sidebar`, `.z-sidebar-overlay`. - Tokens sidebar (largeurs, offsets, z-index) : [index.css](../src/index.css) — "Sidebar layout" et classes `.w-sidebar-expanded`, `.left-sidebar`, `.top-sidebar`, `.bottom-sidebar`, `.z-sidebar`, `.z-sidebar-overlay`.
- Layout primitives (max-width contenu, min-height pages) : mêmes variables `--layout-content-max-width`, `--layout-page-min-height`, etc. Le `<main>` contient un wrapper `max-w-layout-content` pour le contenu. - Layout primitives (max-width contenu, min-height pages) : variables `--layout-content-max-width`, `--layout-page-min-height`, etc. Le `<main>` contient un wrapper `max-w-layout-content` pour le contenu.
- Design tokens SUMI (nomenclature, philosophie) : [DESIGN_TOKENS.md](./DESIGN_TOKENS.md).
- Direction design (esthétique SUMI) : [DESIGN_DIRECTION.md](./DESIGN_DIRECTION.md).

View file

@ -1,401 +1,281 @@
# Design Direction: Surgical Minimalism # Design Direction: SUMI — « Encre, pas néon »
**Last Updated**: 2025-01-27 **Last Updated**: 2026-02-12
**Status**: Active Design Direction **Status**: Active Design Direction
**Purpose**: Define the "Surgical Minimalism" design philosophy for the Veza application **Purpose**: Define the SUMI design philosophy for the Veza application
## Overview ## Overview
"Surgical Minimalism" is a design philosophy that emphasizes: SUMI is a design philosophy rooted in the **sumi-e** (墨絵) ink wash painting tradition. The guiding motto is:
- **Purposeful design**: Every visual element serves a function
- **Increased whitespace**: More breathing room improves readability and hierarchy > **« Encre, pas néon »** — Ink, not neon.
- **Restrained color usage**: Color used strategically, not decoratively
- **Subtle interactions**: Hover effects and animations are functional, not excessive Three pillars:
- **Visual clarity**: Remove unnecessary decorative elements
1. **Surgical Minimalism** — Every visual element serves a function. If it doesn't inform, guide, or delight purposefully, it doesn't belong.
2. **Purposeful Design** — Color, motion, and spacing are intentional tools, never decoration.
3. **Texture over effect** — Depth comes from paper grain, ink wash gradients, and warm neutrals — not from glows, neon pulses, or flashy transforms.
## Core Principles ## Core Principles
### 1. 80/20 Color Rule ### 1. Sumi-e Metaphor
**Principle**: 80% neutral colors, 20% accent colors The UI draws from ink wash painting:
- **80% Neutral**: Dark backgrounds (`kodo-void`, `kodo-ink`, `kodo-graphite`), white text, subtle grays - **Paper grain**: subtle texture through warm neutral backgrounds (`--sumi-bg-base`, `--sumi-bg-raised`, `--sumi-bg-wash`). Light theme evokes washi paper (`--sumi-bg-void: #f0ece4`).
- **20% Color**: Strategic use of `kodo-cyan` for primary actions only, sparing use of other accent colors - **Ink wash gradients**: depth built with opacity layers and glass effects (`--sumi-glass-bg`), not solid neon colors.
- **Pigments, not neon**: four earth-toned accent pigments — **Accent** (slate blue `#7c9dd6`), **Vermillion** (brick red `#d4634a`), **Sage** (muted green `#7a9e6c`), **Gold** (warm ochre `#c9a84c`). Each used sparingly and intentionally.
### 2. Color: Warm Neutrals, Muted Pigments
**Principle**: Warm neutral surfaces, muted earth-toned pigments for accents, high contrast text.
- **Backgrounds**: Warm dark neutrals with subtle blue-violet undertones (`#0c0c0f` → `#1a1a1f``#222228`), not pure black.
- **Text**: Warm off-white (`--sumi-text-primary: #f0ede8`) for primary, stone gray (`--sumi-text-secondary: #a8a4a0`) for secondary. High contrast, WCAG AA compliant.
- **Accents**: Used only for primary actions, active states, semantic status. Never decorative fills.
**Implementation**: **Implementation**:
- Primary actions: Use `kodo-cyan` (buttons, active states, focus rings) - Primary actions: `--sumi-accent` (buttons, active states, focus rings)
- Secondary actions: Use `kodo-steel` instead of cyan - Secondary actions: `--sumi-bg-hover` / `--sumi-border-default`
- Decorative elements: Use neutral colors, avoid color backgrounds - Semantic: `--sumi-success` (sage), `--sumi-warning` (gold), `--sumi-error` (vermillion)
- Status/info: Use semantic colors only when necessary - Decorative elements: neutral backgrounds only
**Target**: Reduce cyan usage by 30-40% from current levels ### 3. Typography: Inter + Space Grotesk
### 2. Increased Whitespace | Role | Font | Token |
|------|------|-------|
| Body text | Inter | `--sumi-font-body` |
| Headings | Space Grotesk | `--sumi-font-heading` |
| Code / mono | JetBrains Mono | `--sumi-font-mono` |
| Serif accents | Noto Serif JP | `--sumi-font-serif` |
**Principle**: More breathing room improves visual hierarchy and reduces cognitive load **Text sizes** follow SUMI scale: `--sumi-text-xs` (0.75rem) through `--sumi-text-4xl` (2.25rem), with `--sumi-text-base` at 0.875rem.
**Implementation**: **Hierarchy**:
- **Card padding**: 32px (was 24px) - `p-8` instead of `p-6` - Headings: `--sumi-text-primary` + `--sumi-font-heading` + `--sumi-weight-semibold`
- **Section spacing**: 32px standard (was 24px) - `space-y-8` instead of `space-y-6` - Body: `--sumi-text-primary` + `--sumi-font-body` + `--sumi-weight-regular`
- **Large sections**: 48px for major containers - `space-y-12` for DashboardPage - Secondary/metadata: `--sumi-text-secondary` or `--sumi-text-tertiary`, sparingly
- **8px grid alignment**: All spacing values align to 8px multiples
**Benefits**: ### 4. Whitespace & Readability
- Improved readability
- Better visual hierarchy
- Reduced visual clutter
- More professional appearance
### 3. Subtle, Purposeful Interactions **Principle**: Generous whitespace improves visual hierarchy and reduces cognitive load.
**Principle**: Hover effects and animations should be functional, not decorative **Spacing tokens** (SUMI scale in [index.css](../src/index.css)):
- `--sumi-space-2` (8px) — base unit
- `--sumi-space-4` (16px) — standard gap
- `--sumi-space-6` (24px) — section gap
- `--sumi-space-8` (32px) — card padding, large section spacing
- `--sumi-space-12` (48px) — page-level spacing
- `--sumi-space-16` (64px) — major separations
**Keep** (Necessary): **Layout gaps**:
- Background color changes: `hover:bg-white/5` for interactive feedback - `--layout-gap` (1rem), `--layout-gap-sm` (0.75rem), `--layout-gap-lg` (1.5rem)
### 5. Subtle, Purposeful Interactions
**Principle**: Hover effects and animations should be functional, not decorative.
**Keep** (functional):
- Background color changes: `hover:bg-[var(--sumi-bg-hover)]` for interactive feedback
- Opacity changes: `group-hover:opacity-100` for functional overlays (play buttons) - Opacity changes: `group-hover:opacity-100` for functional overlays (play buttons)
- Border color changes: `hover:border-white/10` for interactive elements - Border color changes: `hover:border-[var(--sumi-border-strong)]`
- Text color changes: `hover:text-white` for navigation links - Text color changes: `hover:text-[var(--sumi-text-primary)]`
- Transition timing: `--sumi-duration-fast` (150ms) for colors, `--sumi-duration-normal` (200ms) for transforms
- Easing: `--sumi-ease-default` or `--sumi-ease-out`
**Remove** (Excessive): **Anti-patterns** (NEVER do):
- Scale transforms: `hover:scale-[1.02]`, `hover:scale-110` on cards - ❌ Scale transforms on hover: no `hover:scale-[1.02]`, `hover:scale-105`, `hover:scale-110`
- Decorative shadows: `hover:shadow-neon-cyan/20`, `hover:shadow-lg` on cards - ❌ Neon glows: no `shadow-[0_0_15px_rgba(0,255,255,...)]`, no `shadow-neon-*`
- Image zoom effects: `group-hover:scale-110` on decorative images - ❌ Decorative animations: no pulsing, no bouncing, no breathing effects for aesthetics
- Multiple simultaneous effects: Scale + shadow + border combinations - ❌ Multiple simultaneous effects: no scale + shadow + border combos
- ❌ Image zoom on hover: no `group-hover:scale-110` on decorative images
**Target**: Reduce hover effects by 30-40% (remove decorative effects) ### 6. Surfaces & Elevation
### 4. Gradients Used Sparingly Depth is conveyed through **background layers** and **shadows**, not glows:
**Principle**: Gradients reserved for hero sections and functional overlays | Level | Token | Usage |
|-------|-------|-------|
| Void | `--sumi-bg-void` | Page background |
| Base | `--sumi-bg-base` | Main content area |
| Raised | `--sumi-bg-raised` | Sidebar, cards |
| Overlay | `--sumi-bg-overlay` | Dropdowns, popovers |
| Glass | `--sumi-glass-bg` + blur | Header, player bar |
**Keep Gradients**: **Shadows** (SUMI scale): `--sumi-shadow-xs` through `--sumi-shadow-2xl`. Use sparingly — one shadow level per element. `--sumi-shadow-glow` reserved for focus rings only.
- Hero sections: Featured content, landing sections
- Functional overlays: Text readability over images (`bg-gradient-to-t from-black/80`)
- Small decorative elements: Icon containers, visualizations (minimal)
**Remove Gradients**: ### 7. Gradients: Functional Only
- Card backgrounds: Use solid colors (`bg-kodo-ink`, `bg-kodo-graphite`)
- Decorative sections: Replace with solid backgrounds
- Hover overlays: Use solid colors with opacity
**Result**: All card components use solid backgrounds **Keep**:
- Functional overlays for text readability: `bg-gradient-to-t from-black/80`
- Hero sections (featured content, landing)
- Glass effects (via `--sumi-glass-bg` + backdrop-blur)
### 5. 8px Grid System **Remove**:
- Card backgrounds: use solid `--sumi-surface-card`
- Decorative section backgrounds
- Hover overlays: use solid colors with opacity
**Principle**: All spacing aligns to an 8px base grid for visual rhythm ## Sub-Themes: Contextual Accents
**Preferred Values** (8px-aligned): Sub-themes are **contextual accent overrides**, not global theme replacements. They provide feature-specific color accents while the core SUMI palette stays constant.
- `gap-2`, `p-2`, `m-2` (8px) - Base unit
- `gap-4`, `p-4`, `m-4` (16px) - Standard
- `gap-6`, `p-6`, `m-6` (24px) - Large
- `gap-8`, `p-8`, `m-8` (32px) - Extra large (card padding, section spacing)
- `gap-12`, `p-12`, `m-12` (48px) - Section spacing, large containers
- `gap-16`, `p-16`, `m-16` (64px) - Page-level spacing
- `gap-24`, `p-24`, `m-24` (96px) - Maximum spacing
**Avoid** (not 8px-aligned): | Sub-theme | Accent | Token | Context |
- `gap-1`, `p-1`, `m-1` (4px) - Use `gap-2` instead |-----------|--------|-------|---------|
- `gap-3`, `p-3`, `m-3` (12px) - Use `gap-2` or `gap-4` instead | Nature | Sakura pink | `--sakura: #e0a0b8` | Nature/ambient content |
- `gap-10`, `p-10`, `m-10` (40px) - Use `gap-8` or `gap-12` instead | Graffiti | Magenta | `--graffiti-magenta: #c840a0` | Urban/graffiti features |
- `gap-20`, `p-20`, `m-20` (80px) - Use `gap-16` or `gap-24` instead | Gaming | Gold | `--gaming-gold: #d4b040` | Gaming-related features |
| Terminal | Green | `--terminal-green: #3eaa5e` | Developer/terminal features |
| Music | Default accent | `--sumi-accent` | Core music experience |
### 6. Text Color Hierarchy **Rules**:
- Sub-themes affect only their feature area, not the global shell
- Core backgrounds, text colors, and border tokens remain SUMI
- A sub-theme overrides `--sumi-accent` locally, nothing else
**Principle**: Use white for primary content, dim text sparingly for truly secondary information ## Anti-Patterns Reference
**Primary Text**: These patterns contradict SUMI and must be avoided:
- Main content: `text-white` (was `text-kodo-text-main` with beige)
- Headings: `text-white`
- Interactive elements: `text-white` with opacity for hover states
**Secondary Text**: | Anti-pattern | Why | Alternative |
- Truly secondary info: `text-kodo-secondary` or `text-white opacity-80` |--------------|-----|-------------|
- Metadata: `text-kodo-content-dim` | `hover:scale-[1.02]` | Decorative, not functional | `hover:bg-[var(--sumi-bg-hover)]` |
- Use sparingly: Only for information that is genuinely less important | `shadow-neon-cyan/20` | Neon aesthetic, not ink | `--sumi-shadow-sm` |
| `bg-gradient-to-r from-cyan to-blue` | Neon gradient | Solid `--sumi-surface-card` |
**Result**: Better contrast, improved readability, WCAG AA compliant | `animate-pulse` on decorative elements | Distracting | Static or `--sumi-transition-opacity` |
| `text-cyan-400` / `text-kodo-cyan` | Old Kodo neon palette | `--sumi-accent` or `--sumi-text-link` |
## Design Tokens | `bg-kodo-void` / `bg-kodo-ink` | Old Kodo tokens | `--sumi-bg-void` / `--sumi-bg-base` |
| Class-based theme toggle (`dark:`) | Stale pattern | `[data-theme]` attribute |
### Section Spacing
```css
--section-spacing: 2rem; /* 32px - Standard section spacing (4× base) */
--section-spacing-lg: 3rem; /* 48px - Large section spacing (6× base) */
```
**Usage**:
- Standard sections: `space-y-8` (32px)
- Large containers: `space-y-12` (48px)
- Or use CSS variable: `space-y-[var(--section-spacing)]`
### Color Usage Guidelines
**Primary Actions** (Use Cyan):
- Primary buttons: `bg-kodo-cyan`
- Active navigation: `text-kodo-cyan`, `bg-kodo-cyan/10`
- Focus rings: `focus-visible:ring-kodo-cyan`
- Critical status indicators
**Secondary Actions** (Use Steel):
- Outline buttons: `border-kodo-steel`, `hover:border-kodo-steel/50`
- Secondary navigation: `text-kodo-steel`
- Non-primary interactive elements
**Neutral Backgrounds**:
- Cards: `bg-kodo-graphite` or `bg-kodo-ink`
- Elevated surfaces: `bg-kodo-ink`
- Main background: `bg-kodo-void`
## Implementation Checklist ## Implementation Checklist
When applying "Surgical Minimalism" to a component or page, use this comprehensive checklist: When applying SUMI to a component or page:
### Color (80/20 Rule) ### Color & Surface
- [ ] Backgrounds use SUMI tokens (`--sumi-bg-*`, `--sumi-surface-*`)
- [ ] Text uses `--sumi-text-primary` (not `text-white` or `text-kodo-*`)
- [ ] Accents use `--sumi-accent` family (not `kodo-cyan`)
- [ ] Semantic colors use `--sumi-success`, `--sumi-warning`, `--sumi-error`
- [ ] No neon colors, no `kodo-*` tokens
- [ ] Cards use `--sumi-surface-card` (solid, no gradient)
#### Primary Actions (Use Cyan) ### Spacing & Layout
- [ ] Primary buttons use `bg-kodo-cyan` (not outline/secondary buttons) - [ ] Spacing uses SUMI scale (`--sumi-space-*`) or Tailwind equivalents
- [ ] Active navigation states use `text-kodo-cyan` or `bg-kodo-cyan/10` - [ ] Layout uses SUMI layout tokens (`--sumi-max-width`, `--sumi-header-height`, etc.)
- [ ] Focus rings use `focus-visible:ring-kodo-cyan` - [ ] Generous whitespace between sections
- [ ] Critical status indicators use cyan appropriately
- [ ] No cyan on decorative elements or backgrounds
#### Secondary Actions (Use Steel) ### Interactions
- [ ] Outline buttons use `border-kodo-steel` (not `border-kodo-cyan`) - [ ] Hover effects are subtle: background/opacity/border color only
- [ ] Outline button hover states use `hover:border-kodo-steel/50` (not cyan) - [ ] No scale transforms on interactive elements
- [ ] Secondary navigation items use `text-kodo-steel` (not cyan) - [ ] No decorative shadows or glows on hover
- [ ] Non-primary interactive elements use steel colors - [ ] Transitions use `--sumi-duration-fast` / `--sumi-ease-default`
- [ ] Icon buttons (non-primary) use steel, not cyan
#### Neutral Backgrounds ### Typography
- [ ] Cards use `bg-kodo-graphite` or `bg-kodo-ink` (solid colors, no gradients) - [ ] Body text uses `--sumi-font-body` (Inter)
- [ ] Elevated surfaces use `bg-kodo-ink` - [ ] Headings use `--sumi-font-heading` (Space Grotesk)
- [ ] Main backgrounds use `bg-kodo-void` - [ ] Text sizes follow SUMI scale (`--sumi-text-*`)
- [ ] No decorative color backgrounds (use neutral colors) - [ ] Text contrast meets WCAG AA
#### Color Ratio Check ### Glass & Elevation
- [ ] Approximately 80% of the component uses neutral colors (void, ink, graphite, steel, white) - [ ] Glass surfaces use `--sumi-glass-bg` + `backdrop-blur`
- [ ] Approximately 20% uses accent colors (cyan for primary actions only) - [ ] Shadows use SUMI scale (`--sumi-shadow-*`)
- [ ] No excessive color usage that breaks the 80/20 rule - [ ] Focus rings use `--sumi-shadow-glow`
### Spacing (8px Grid Alignment) ### Theme Compatibility
- [ ] Component works with `[data-theme="dark"]` and `[data-theme="light"]`
#### Grid Alignment - [ ] No hardcoded colors that break in light theme
- [ ] All spacing values are multiples of 8px (0, 8, 16, 24, 32, 48, 64, 96px) - [ ] Borders use `--sumi-border-*` tokens
- [ ] No use of non-8px values (4px, 12px, 40px, 80px) unless absolutely necessary
- [ ] Preferred values: `gap-2` (8px), `gap-4` (16px), `gap-6` (24px), `gap-8` (32px), `gap-12` (48px), `gap-16` (64px), `gap-24` (96px)
#### Card Padding
- [ ] Card padding is 32px (`p-8`) - increased from previous 24px (`p-6`)
- [ ] CardHeader, CardContent, CardFooter all use `p-8` (not `p-6`)
- [ ] Custom cards follow the same 32px padding standard
#### Section Spacing
- [ ] Standard section spacing is 32px (`space-y-8`) - increased from 24px (`space-y-6`)
- [ ] Large section containers use 48px (`space-y-12`) for major sections
- [ ] Page-level spacing uses 64px (`space-y-16`) or 96px (`space-y-24`) for maximum separation
- [ ] CSS variables can be used: `space-y-[var(--section-spacing)]` (32px) or `space-y-[var(--section-spacing-lg)]` (48px)
#### Whitespace Assessment
- [ ] Adequate breathing room between major sections
- [ ] Sufficient spacing between related elements (not cramped)
- [ ] Visual hierarchy is clear through spacing (not just color)
- [ ] No excessive spacing that creates disconnected feeling
### Interactions (Subtle & Functional)
#### Hover Effects - Keep (Functional)
- [ ] Background color changes: `hover:bg-white/5` for interactive feedback
- [ ] Opacity changes: `group-hover:opacity-100` for functional overlays (play buttons, tooltips)
- [ ] Border color changes: `hover:border-white/10` or `hover:border-kodo-steel/50` for interactive elements
- [ ] Text color changes: `hover:text-white` for navigation links
- [ ] Transition duration is reasonable: `transition-colors duration-200` or `transition-opacity duration-200`
#### Hover Effects - Remove (Excessive)
- [ ] No scale transforms on cards: Remove `hover:scale-[1.02]`, `hover:scale-110`, `hover:scale-105`
- [ ] No decorative shadows: Remove `hover:shadow-neon-cyan/20`, `hover:shadow-lg` on cards
- [ ] No image zoom effects: Remove `group-hover:scale-110` on decorative images
- [ ] No multiple simultaneous effects: Simplify combinations of scale + shadow + border
- [ ] No excessive glow effects: Remove `hover:shadow-[0_0_15px_rgba(255,255,255,0.5)]`
#### Animation Assessment
- [ ] All animations serve a functional purpose (feedback, state changes)
- [ ] No purely decorative animations
- [ ] Transitions are smooth but not distracting
- [ ] Performance is maintained (no janky animations)
### Visual Elements (Clarity & Purpose)
#### Gradients
- [ ] No gradients on card backgrounds (use solid `bg-kodo-graphite` or `bg-kodo-ink`)
- [ ] Gradients only in hero sections or featured content sections
- [ ] Functional overlay gradients for text readability are acceptable: `bg-gradient-to-t from-black/80`
- [ ] Small decorative gradients on icon containers are minimal and acceptable
- [ ] No decorative gradient overlays on cards (e.g., `bg-gradient-to-b from-white/5 to-transparent`)
#### Text Color Hierarchy
- [ ] Primary text uses `text-white` (not beige or dim colors)
- [ ] Headings use `text-white` for maximum contrast
- [ ] Secondary text uses `text-white opacity-80` or `text-kodo-content-dim` sparingly
- [ ] Metadata uses dim text only when genuinely less important
- [ ] Text contrast meets WCAG AA standards
#### Decorative Elements
- [ ] Unnecessary decorative elements are removed
- [ ] Every visual element serves a purpose (functional, not just aesthetic)
- [ ] No excessive borders, shadows, or highlights
- [ ] Visual clutter is minimized
### Component-Specific Checks
#### Buttons
- [ ] Primary buttons: `bg-kodo-cyan` with `text-black` or `text-white`
- [ ] Secondary/outline buttons: `border-kodo-steel` (not cyan)
- [ ] Hover states are subtle: `hover:opacity-90` or `hover:bg-white/5`
- [ ] No scale transforms on hover
- [ ] Focus states are clear: `focus-visible:ring-kodo-cyan`
#### Cards
- [ ] Padding is 32px (`p-8`)
- [ ] Background is solid color (`bg-kodo-graphite` or `bg-kodo-ink`)
- [ ] No gradients on background
- [ ] Hover effect is subtle: `hover:bg-white/5 transition-colors duration-200`
- [ ] No scale transforms or decorative shadows
- [ ] Border uses `border-kodo-steel` if needed (not cyan)
#### Navigation
- [ ] Active states use `text-kodo-cyan` or `bg-kodo-cyan/10`
- [ ] Inactive states use `text-kodo-steel` or `text-white`
- [ ] Hover states are subtle: `hover:text-white` or `hover:bg-white/5`
- [ ] No scale transforms on icons or text
#### Forms
- [ ] Input focus states use `focus-visible:ring-kodo-cyan`
- [ ] Labels use `text-white` for primary text
- [ ] Helper text uses dim text sparingly
- [ ] Error states use appropriate semantic colors
- [ ] Spacing between form fields aligns to 8px grid
#### Pages
- [ ] Main container spacing is 32px (`space-y-8`) or 48px (`space-y-12`) for large sections
- [ ] Page padding is 32px (`p-8`) or appropriate for layout
- [ ] Section hierarchy is clear through spacing
- [ ] No excessive decorative elements
- [ ] Color usage follows 80/20 rule
### Final Validation
#### Overall Assessment
- [ ] Component/page follows all "Surgical Minimalism" principles
- [ ] Visual hierarchy is clear and purposeful
- [ ] Whitespace is adequate and improves readability
- [ ] Color usage is restrained and strategic
- [ ] Interactions are subtle and functional
- [ ] No unnecessary decorative elements remain
- [ ] Component is accessible (WCAG AA compliant)
- [ ] Performance is maintained (no excessive animations or effects)
#### Documentation
- [ ] Component is documented if it's a reusable component
- [ ] Design decisions are clear and align with this direction
- [ ] Future maintainers can understand the design choices
## Examples ## Examples
### ✅ Good: Surgical Minimalism Applied ### ✅ Good: SUMI Applied
```tsx ```tsx
// Card with solid background, subtle hover, adequate padding // Card with SUMI tokens
<Card className="p-8 hover:bg-white/5 transition-colors"> <Card className="bg-[var(--sumi-surface-card)] border border-[var(--sumi-border-faint)] p-8
hover:bg-[var(--sumi-bg-hover)] transition-colors duration-[var(--sumi-duration-fast)]">
<CardHeader> <CardHeader>
<CardTitle className="text-white">Title</CardTitle> <CardTitle className="text-[var(--sumi-text-primary)] font-heading">Title</CardTitle>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<p className="text-white opacity-80">Content</p> <p className="text-[var(--sumi-text-secondary)]">Content</p>
</CardContent> </CardContent>
</Card> </Card>
// Button with cyan only for primary actions // Button with SUMI accent
<Button variant="default" className="bg-kodo-cyan">Primary Action</Button> <Button className="bg-[var(--sumi-accent)] text-[var(--sumi-text-inverse)]">
<Button variant="outline" className="border-kodo-steel hover:border-kodo-steel/50"> Primary Action
</Button>
<Button variant="outline" className="border-[var(--sumi-border-default)]
hover:border-[var(--sumi-border-strong)]">
Secondary Action Secondary Action
</Button> </Button>
// Section with proper spacing
<div className="space-y-8">
<Section1 />
<Section2 />
</div>
``` ```
### ❌ Avoid: Excessive Decoration ### ❌ Avoid: Anti-SUMI Patterns
```tsx ```tsx
// Card with gradient, scale transform, decorative shadow // Neon glow + scale transform + gradient
<Card className="p-6 bg-gradient-to-r from-kodo-ink to-kodo-graphite hover:scale-[1.02] hover:shadow-neon-cyan/20"> <Card className="bg-gradient-to-r from-kodo-ink to-kodo-graphite
{/* Avoid */} hover:scale-[1.02] hover:shadow-neon-cyan/20">
{/* ❌ Gradient bg, scale, neon glow */}
</Card> </Card>
// Button with cyan for secondary actions // Kodo tokens (deprecated)
<Button variant="outline" className="border-kodo-cyan hover:border-kodo-cyan/50"> <Button className="bg-kodo-cyan text-black">
{/* Should use kodo-steel */} {/* ❌ Use --sumi-accent instead */}
</Button> </Button>
// Section with insufficient spacing // Decorative animation
<div className="space-y-4"> <div className="animate-pulse bg-cyan-500/20">
{/* Should be space-y-8 */} {/* ❌ Neon color + decorative animation */}
</div> </div>
``` ```
## Migration Path ## Migration Path
### Completed Actions ### Completed
1. ✅ SUMI token system defined in `index.css` (`:root` + `[data-theme="light"]`)
1. ✅ **Text Colors**: Changed primary text to white, use dim text sparingly 2. ✅ Theme switching migrated from class to `[data-theme]` attribute
2. ✅ **Card Padding**: Increased from 24px to 32px 3. ✅ Typography tokens: Inter (body) + Space Grotesk (headings) + JetBrains Mono (code)
3. ✅ **Section Spacing**: Increased from 24px to 32px (standard), 48px (large) 4. ✅ Glass effects on header and player bar
4. ✅ **Hover Effects**: Removed excessive scale transforms and decorative shadows 5. ✅ Shadow and z-index scales defined
5. ✅ **Gradients**: Removed from cards, kept only in hero sections 6. ✅ Contextual accent tokens (graffiti, gaming, terminal, sakura)
6. ✅ **8px Grid**: Documented and verified alignment
### In Progress ### In Progress
- Component migration from `kodo-*` tokens to `--sumi-*` tokens
- **Color Reduction**: Audit complete, replacement in progress - Audit and removal of remaining neon glows and scale transforms
- **Component Updates**: Applying principles to remaining components - Light theme (Washi Paper) refinement
### Future Work ### Future Work
- Enforce SUMI tokens via linting rules
- Apply to all remaining pages and components - Paper grain texture as optional background layer
- Create design system components that enforce principles - Ink wash gradient presets for hero/feature sections
- Add linting rules to prevent violations - Sub-theme contextual scoping
## References ## References
- **8px Grid System**: `apps/web/src/styles/GRID_SYSTEM.md` - **SUMI tokens source**: `apps/web/src/index.css``:root` and `[data-theme="light"]`
- **Cyan Usage Audit**: `apps/web/docs/CYAN_USAGE_AUDIT.md` - **App Shell layout**: `apps/web/docs/APP_SHELL.md`
- **Hover Effects Audit**: `apps/web/docs/HOVER_EFFECTS_AUDIT.md` - **Design Tokens doc**: `apps/web/docs/DESIGN_TOKENS.md`
- **Gradient Usage Verification**: `apps/web/docs/GRADIENT_USAGE_VERIFICATION.md` - **Storybook contract**: `apps/web/docs/STORYBOOK_CONTRACT.md`
- **Section Spacing Audit**: `apps/web/docs/SECTION_SPACING_AUDIT.md`
- **Design Tokens**: `apps/web/src/styles/design-tokens.css`
## Benefits ## Benefits
**User Experience**: **User Experience**:
- Reduced cognitive load - Reduced cognitive load — warm neutrals are easier on the eyes
- Improved readability - Improved readability — high contrast text, generous whitespace
- Better visual hierarchy - Better visual hierarchy — depth through layers, not decoration
- More professional appearance - Professional, distinctive aesthetic — ink wash, not neon
- Faster information processing
**Developer Experience**: **Developer Experience**:
- Clear design principles - Single token system (`--sumi-*`) — no ambiguity between old/new tokens
- Consistent patterns - Clear anti-patterns — easy to audit and enforce
- Reusable utilities - Consistent patterns across dark and light themes
- Easier maintenance - Meaningful names tied to the sumi-e metaphor
- Better scalability
**Accessibility**: **Accessibility**:
- WCAG AA compliant contrast ratios - WCAG AA compliant contrast ratios
- Clear focus states - Clear focus states (`--sumi-shadow-glow`)
- Reduced visual noise - Reduced visual noise and motion
- Better screen reader experience - Functional-only interactions

View file

@ -1,134 +1,301 @@
# Design Tokens — Référence # Design Tokens — SUMI Design System
Source de vérité pour les tokens du design system Veza/Kodo. Toute valeur despacement, couleur, ombre, typographie ou transition doit sappuyer sur ces tokens ou sur léchelle Tailwind documentée ici. Source of truth: [`src/index.css`](../src/index.css). All `--sumi-*` variables are defined there. Do not create competing token files.
## 1. Espacements (layout et sections) Theme switching uses `[data-theme="dark"]` (default, applied on `:root`) and `[data-theme="light"]` attributes.
Définis dans [index.css](../src/index.css) (`:root`) et [design-tokens.css](../src/styles/design-tokens.css) (scale Tailwind). ---
| Variable | Valeur | Rôle | ## 1. Colors
|----------|--------|------|
| `--layout-gap` | 1rem (16px) | Gap par défaut entre sections (align Tailwind gap-4) |
| `--layout-gap-sm` | 0.75rem (12px) | Gap serré (gap-3) |
| `--layout-gap-lg` | 1.5rem (24px) | Gap large (gap-6) |
Scale complète (4px base) : voir [SPACING_GUIDE.md](SPACING_GUIDE.md) et `design-tokens.css` (`--spacing-0` à `--spacing-96`). Utiliser les classes Tailwind `gap-*`, `p-*`, `m-*`, `space-*` de préférence aux valeurs arbitraires. ### Backgrounds
## 2. Couleurs | Token | Dark | Light | Role |
|-------|------|-------|------|
| `--sumi-bg-void` | `#0c0c0f` | `#f0ece4` | Deepest background |
| `--sumi-bg-base` | `#121215` | `#f6f3ed` | App background |
| `--sumi-bg-raised` | `#1a1a1f` | `#ffffff` | Cards, sidebar |
| `--sumi-bg-overlay` | `#222228` | `#ffffff` | Popovers, dropdowns |
| `--sumi-bg-hover` | `#2a2a31` | `#ede9e1` | Hover state |
| `--sumi-bg-active` | `#32323a` | `#e4e0d8` | Active/pressed state |
| `--sumi-bg-wash` | `#18181d` | `#f8f6f1` | Subtle wash area |
- **Kodo (primaire)** : [index.css](../src/index.css) — `--background`, `--foreground`, `--primary`, `--muted`, `--border`, etc. ### Surfaces
- **Sidebar** : `--sidebar`, `--sidebar-foreground`, `--sidebar-primary`, etc. (index.css).
- **Mapping et usage** : [src/styles/COLOR_USAGE.md](../src/styles/COLOR_USAGE.md).
Ne pas utiliser les couleurs par défaut Tailwind (slate, gray, zinc, etc.) ; privilégier les tokens Kodo (kodo-void, kodo-cyan, etc.). | Token | Role |
|-------|------|
| `--sumi-surface-inset` | Inset/recessed areas |
| `--sumi-surface-subtle` | Subtle differentiation |
| `--sumi-surface-card` | Card backgrounds |
| `--sumi-surface-elevated` | Elevated panels |
## 3. Typographie ### Text — Warm neutrals
Échelle Tailwind utilisée (tailles de texte) : | Token | Dark | Light | Role |
|-------|------|-------|------|
| `--sumi-text-primary` | `#f0ede8` | `#1a1816` | Primary content |
| `--sumi-text-secondary` | `#a8a4a0` | `#5c5854` | Secondary content |
| `--sumi-text-tertiary` | `#706c68` | `#8a8580` | Tertiary/hints |
| `--sumi-text-disabled` | `#4a4844` | `#b5b0aa` | Disabled state |
| `--sumi-text-inverse` | `#121215` | `#f0ede8` | Inverse (on accent bg) |
| `--sumi-text-link` | `#8baade` | `#4a6fa5` | Links |
| Classe | Taille (rem) | Usage | ### Borders
|--------|--------------|--------|
| `text-xs` | 0.75rem | Caption, labels secondaires |
| `text-sm` | 0.875rem | Labels, métadonnées |
| `text-base` | 1rem | Corps de texte |
| `text-lg` | 1.125rem | Sous-titres |
| `text-xl` | 1.25rem | Titres de section |
| `text-2xl` | 1.5rem | Titres de page |
| `text-3xl` | 1.875rem | Titres principaux |
| `text-4xl` | 2.25rem | Hero / titres très visibles |
Line-height et font-weight : suivre les utilitaires Tailwind (`leading-*`, `font-normal`, `font-medium`, `font-semibold`, `font-bold`). Ne pas utiliser de tailles arbitraires (`text-[14px]`, etc.) sauf exception documentée (ex. SVG charts). | Token | Role |
|-------|------|
| `--sumi-border-faint` | Barely visible dividers |
| `--sumi-border-default` | Standard borders |
| `--sumi-border-strong` | Emphasized borders |
| `--sumi-border-focus` | Focus rings |
| `--sumi-border-accent` | Accent-tinted borders |
### Classes utilitaires typographiques (index.css `@layer utilities`) ### Pigments (accent colors)
| Classe | Définition | Usage | 4 pigments provide all accent color needs:
|--------|------------|-------|
| `.text-display` | `text-4xl font-bold tracking-tight` | Hero / titres très visibles |
| `.text-heading-1` | `text-3xl font-semibold tracking-tight` | Titre principal de page (H1) |
| `.text-heading-2` | `text-2xl font-semibold` | Titre de section (H2) |
| `.text-heading-3` | `text-xl font-medium` | Sous-section (H3) |
| `.text-heading-4` | `text-lg font-medium` | Sous-titre (H4) |
| `.text-body-lg` | `text-base leading-relaxed` | Corps de texte élargi |
| `.text-body` | `text-sm leading-relaxed` | Corps de texte standard |
| `.text-caption` | `text-xs text-muted-foreground` | Légendes, durées, timestamps |
| `.text-label` | `text-xs font-medium uppercase tracking-wider text-muted-foreground` | Labels de champs |
Utiliser ces classes en priorité pour les headings et body text. Ajouter `font-display` séparément si la police Orbitron est souhaitée. | Pigment | Token | Dark hex | Role |
|---------|-------|----------|------|
| **Indigo** | `--sumi-accent` | `#7c9dd6` | Primary accent, links, focus |
| **Vermillion** | `--sumi-vermillion` | `#d4634a` | Destructive, errors, live |
| **Sage** | `--sumi-sage` | `#7a9e6c` | Success, online, positive |
| **Gold** | `--sumi-gold` | `#c9a84c` | Warnings, achievements |
### Hiérarchie visuelle (usage recommandé) Each pigment has `-hover` and `-subtle` variants. Indigo also has `-active`, `-muted`, and `-emphasis`.
| Rôle | Classe | Contexte | ### Semantic aliases
|------|--------|----------|
| Titre de page | `.text-heading-1` (ou `.text-display` pour hero) | H1 de la page (Dashboard, Playlists, etc.) |
| Sous-titre / section | `.text-heading-2` ou `.text-heading-3` | Titres de blocs |
| Label / métadonnée | `.text-label` ou `text-sm` | Labels de champs, infos secondaires |
| Corps | `.text-body-lg` ou `.text-body` | Texte courant |
| Caption / timestamps | `.text-caption` | Légendes, durées, timestamps |
Contraste : privilégier `text-foreground` pour linfo principale et `text-muted-foreground` pour linfo secondaire (style Spotify : titre + artiste, description en gris). | Token | Maps to |
|-------|---------|
| `--sumi-success` | `--sumi-sage` |
| `--sumi-warning` | `--sumi-gold` |
| `--sumi-error` | `--sumi-vermillion` |
| `--sumi-info` | `--sumi-accent` |
### Exceptions (tailles arbitraires typo) ### shadcn/Radix mapping
- **Avatar size `xs`** : le composant [avatar.tsx](../src/components/ui/avatar.tsx) utilise `text-[10px]` pour les initiales en taille `xs` (w-6 h-6) pour garder une proportion lisible. Exception documentée — ne pas remplacer par `text-xs` dans ce cas. Standard `--background`, `--foreground`, `--primary`, `--muted`, `--border`, etc. are all aliased to `--sumi-*` tokens in `index.css`. Use Tailwind classes (`bg-background`, `text-foreground`, `text-primary`, `text-muted-foreground`) as usual — they resolve to SUMI values.
- **Badge** : la doc du composant badge mentionne `text-[10px]` comme référence de style ; les usages réels du composant utilisent léchelle (ex. `text-xs`).
## 4. Ombres **Do not** use raw Tailwind color palettes (slate, gray, zinc, etc.). Always use the semantic tokens.
Définies dans [design-system.css](../src/styles/design-system.css). ---
| Variable | Rôle | ## 2. Typography
|----------|------|
| `--shadow-sm` | Ombres légères |
| `--shadow-md` | Ombres moyennes, tooltips |
| `--shadow-lg` | Cartes surélevées |
| `--shadow-xl` | Modales |
| `--shadow-soft` | Ombres douces |
| `--shadow-card` | Cartes (alias `--shadow-soft`) |
| `--shadow-modal` | Modales (alias `--shadow-xl`) |
| `--shadow-tooltip` | Tooltips (alias `--shadow-md`) |
Classes utilitaires dans index.css : `.shadow-card`, `.shadow-modal`, `.shadow-tooltip`, `.shadow-card-hover`, `.shadow-card-glow-cyan`, `.shadow-card-glow-magenta`. Tokens additionnels : `--sidebar-active-indicator`, `--button-primary-glow`, `--button-primary-glow-hover`, `--player-thumb-glow`, `--player-hover-glow`, `--queue-item-current-glow`, `--slider-thumb-glow`, `--status-dot-glow-cyan`, `--status-dot-glow-lime`, `--status-dot-glow-magenta` (design-system.css) avec classes `.sidebar-active-indicator`, `.shadow-button-primary-glow`, `.shadow-button-primary-glow-hover`, `.shadow-player-thumb`, `.shadow-player-hover`, `.shadow-queue-item-current`, `.shadow-slider-thumb`, `.shadow-status-dot-cyan`, `.shadow-status-dot-lime`, `.shadow-status-dot-magenta`. Couverture / hero : `--shadow-cover-depth` (`.shadow-cover-depth`). Gaming / XP : `--shadow-gold-glow` (`.shadow-gold-glow`). FAB : `--shadow-fab-glow`, `--shadow-fab-glow-hover` (`.shadow-fab-glow`, `.shadow-fab-glow-hover`). ### Font stacks
## 5. Layout shell (sidebar, header, main) | Token | Font | Usage |
|-------|------|-------|
| `--sumi-font-body` | Inter | Body text (Tailwind `font-sans`) |
| `--sumi-font-heading` | Space Grotesk | Headings (Tailwind `font-heading`) |
| `--sumi-font-mono` | JetBrains Mono | Code (Tailwind `font-mono`) |
| `--sumi-font-serif` | Noto Serif JP | Decorative (Tailwind `font-serif`) |
Définis dans [index.css](../src/index.css). Référence complète : [APP_SHELL.md](APP_SHELL.md). ### Type scale (`--sumi-text-*`)
- **Sidebar** : `--sidebar-width-expanded`, `--sidebar-width-collapsed`, `--sidebar-offset-*`, `--sidebar-z-index`. | Token | Size | Tailwind class |
- **Header** : `--header-height`, `--header-left-expanded`, `--header-left-collapsed`. |-------|------|----------------|
- **Main** : `--main-offset-top`, `--main-offset-bottom`, `--main-margin-left-expanded`, `--main-margin-left-collapsed`. | `--sumi-text-4xl` | 2.25rem | `text-4xl` |
- **Max heights (drawers, panels, lists)** : `--layout-drawer-max-height` (60vh), `--layout-panel-max-height` (70vh), `--layout-list-max-height` (25rem) — classes `.max-h-layout-drawer`, `.max-h-layout-panel`, `.max-h-layout-list`. | `--sumi-text-3xl` | 1.875rem | `text-3xl` |
- **Modales** : `--layout-modal-max-height` (85vh), `--layout-modal-max-height-sm` (80vh), `--layout-modal-max-height-xs` (70vh), `--layout-modal-max-height-lg` (90vh) — classes `.max-h-layout-modal`, `.max-h-layout-modal-sm`, `.max-h-layout-modal-xs`, `.max-h-layout-modal-lg`. | `--sumi-text-2xl` | 1.5rem | `text-2xl` |
- **Lyrics / hero** : `--layout-lyrics-height` (60vh), `--layout-lyrics-height-sm` (50vh) — classes `.h-layout-lyrics`, `.h-layout-lyrics-sm`. | `--sumi-text-xl` | 1.25rem | `text-xl` |
- **Chat / full-page** : `--layout-chat-height` (calc(100vh - 6.25rem)), `--layout-chat-main-height` (calc(100vh - 6rem)), `--layout-stream-height` (calc(100vh - 6rem)), `--layout-modal-full-height` (calc(100vh - 2rem)) — classes `.h-layout-chat`, `.h-layout-chat-main`, `.h-layout-stream`, `.h-layout-modal-full`. | `--sumi-text-lg` | 1.125rem | `text-lg` |
- **Modal hauteur fixe** : `--layout-modal-max-height-sm` (80vh) — classe `.h-layout-modal-sm` pour modales type cropper. | `--sumi-text-md` | 1rem | — |
| `--sumi-text-base` | 0.875rem | `text-sm` |
| `--sumi-text-sm` | 0.8125rem | — |
| `--sumi-text-xs` | 0.75rem | `text-xs` |
Ne pas définir de variables concurrentes (ex. `--sidebar-width`, `--header-height`) ailleurs ; index.css est la source unique pour le shell. ### Utility classes (Tailwind-friendly)
## 6. Transitions et animations | Class | Definition |
|-------|------------|
| `.text-display` | `text-4xl font-bold tracking-tight` |
| `.text-heading-1` | `text-3xl font-semibold tracking-tight` |
| `.text-heading-2` | `text-2xl font-semibold` |
| `.text-heading-3` | `text-xl font-medium` |
| `.text-heading-4` | `text-lg font-medium` |
| `.text-body-lg` | `text-base leading-relaxed` |
| `.text-body` | `text-sm leading-relaxed` |
| `.text-caption` | `text-xs text-muted-foreground` |
| `.text-label` | `text-xs font-medium uppercase tracking-wider text-muted-foreground` |
Définies dans [design-system.css](../src/styles/design-system.css). ### SUMI typography classes (token-driven)
| Variable | Valeur | Usage | `.sumi-display`, `.sumi-h1` through `.sumi-h4`, `.sumi-body-lg`, `.sumi-body`, `.sumi-body-sm`, `.sumi-caption`, `.sumi-label`, `.sumi-mono` — these use `--sumi-*` variables directly for font-size, weight, line-height, and letter-spacing. Use these for finer control over the SUMI type scale.
|----------|--------|--------|
| `--duration-instant` | 100ms | Feedback immédiat |
| `--duration-fast` | 150ms | Hover, focus |
| `--duration-normal` | 250ms | Sidebar, modales |
| `--duration-immersive` | 200ms | Micro-interactions (hover, focus) |
| `--duration-slow` | 400ms | Animations visibles |
| `--duration-slower` | 600ms | Transitions longues |
| `--ease-out` | cubic-bezier(0.33, 1, 0.68, 1) | Sortie |
| `--ease-in-out` | cubic-bezier(0.65, 0, 0.35, 1) | Entrée/sortie |
| `--ease-bounce` | cubic-bezier(0.34, 1.56, 0.64, 1) | Rebond |
| `--ease-spring` | cubic-bezier(0.175, 0.885, 0.32, 1.275) | Spring |
Utiliser ces variables dans les transitions (ex. `transition-all var(--duration-normal) var(--ease-out)`). ### Visual hierarchy (recommended usage)
## 7. Exceptions (valeurs arbitraires) | Role | Class | Context |
|------|-------|---------|
| Page title | `.text-heading-1` / `.text-display` | H1 |
| Section title | `.text-heading-2` / `.text-heading-3` | H2, H3 |
| Label / metadata | `.text-label` / `text-sm` | Field labels |
| Body | `.text-body-lg` / `.text-body` | Running text |
| Caption | `.text-caption` | Timestamps, legends |
Les règles ESLint interdisent les classes arbitraires pour `w-[...]`, `h-[...]`, `rounded-[...]`, `shadow-[...]`, etc. Exceptions autorisées avec commentaire `eslint-disable` : Use `text-foreground` for primary info, `text-muted-foreground` for secondary.
- SVG ou canvas (ex. `text-[2px]` pour axes de graphiques). ---
- Composants tiers dont on ne contrôle pas le markup.
- Cas documentés dans ce fichier ou en PR avec justification.
Voir aussi : [.cursorrules](../.cursorrules) (layout primitives, pas de valeurs arbitraires pour espacements/tailles). ## 3. Spacing
**Base grid: 4px.** Use the standard Tailwind spacing scale (`gap-*`, `p-*`, `m-*`, `space-*`).
SUMI spacing tokens in `index.css` (for reference — prefer Tailwind classes):
| Token | Value |
|-------|-------|
| `--sumi-space-0-5` | 2px |
| `--sumi-space-1` | 4px |
| `--sumi-space-1-5` | 6px |
| `--sumi-space-2` | 8px |
| `--sumi-space-3` | 12px |
| `--sumi-space-4` | 16px |
| `--sumi-space-5` | 20px |
| `--sumi-space-6` | 24px |
| `--sumi-space-8` | 32px |
| `--sumi-space-10` | 40px |
| `--sumi-space-12` | 48px |
| `--sumi-space-16` | 64px |
| `--sumi-space-20` | 80px |
Layout gaps: `--layout-gap` (16px), `--layout-gap-sm` (12px), `--layout-gap-lg` (24px).
---
## 4. Radius
| Token | Value | Usage |
|-------|-------|-------|
| `--sumi-radius-xs` | 2px | Badges, tags |
| `--sumi-radius-sm` | 4px | Buttons, inputs |
| `--sumi-radius-md` | 6px | Cards (default `--radius`) |
| `--sumi-radius-lg` | 12px | Panels, dialogs |
| `--sumi-radius-xl` | 16px | Large cards |
| `--sumi-radius-2xl` | 20px | Hero sections |
| `--sumi-radius-full` | 9999px | Pills, avatars |
Tailwind mapping: `rounded-sm``--sumi-radius-sm`, `rounded-md``--sumi-radius-md`, etc.
---
## 5. Shadows
Defined in `:root` and overridden in `[data-theme="light"]`.
| Token | Role |
|-------|------|
| `--sumi-shadow-xs` | Subtle elevation |
| `--sumi-shadow-sm` | Buttons, small cards |
| `--sumi-shadow-md` | Tooltips, dropdowns |
| `--sumi-shadow-lg` | Cards, panels |
| `--sumi-shadow-xl` | Modals, dialogs |
| `--sumi-shadow-2xl` | Full overlays |
| `--sumi-shadow-glow` | Focus ring glow (Indigo-tinted) |
| `--sumi-shadow-glow-lg` | Large ambient glow |
### Glass effect
| Token | Value |
|-------|-------|
| `--sumi-glass-bg` | Semi-transparent bg |
| `--sumi-glass-border` | Subtle glass border |
| `--sumi-glass-blur` | 12px blur |
Classes: `.glass` / `.sumi-glass` apply all three properties + `backdrop-filter`.
---
## 6. Z-Index
| Token | Value | Usage |
|-------|-------|-------|
| `--sumi-z-base` | 0 | Default layer |
| `--sumi-z-raised` | 10 | Raised content |
| `--sumi-z-dropdown` | 100 | Dropdown menus |
| `--sumi-z-sticky` | 200 | Sticky headers, player |
| `--sumi-z-overlay` | 300 | Overlays |
| `--sumi-z-modal` | 400 | Modals |
| `--sumi-z-popover` | 500 | Popovers |
| `--sumi-z-toast` | 600 | Toast notifications |
| `--sumi-z-tooltip` | 700 | Tooltips |
| `--sumi-z-max` | 999 | Absolute top layer |
---
## 7. Motion
### Durations
| Token | Value | Usage |
|-------|-------|-------|
| `--sumi-duration-instant` | 75ms | Immediate feedback |
| `--sumi-duration-fast` | 150ms | Hover, focus, color changes |
| `--sumi-duration-normal` | 200ms | Sidebar, modals, transforms |
| `--sumi-duration-slow` | 300ms | Complex transitions |
| `--sumi-duration-slower` | 500ms | Page-level transitions |
### Easings
| Token | Curve | Usage |
|-------|-------|-------|
| `--sumi-ease-default` | `cubic-bezier(0.25, 0.1, 0.25, 1)` | General purpose |
| `--sumi-ease-out` | `cubic-bezier(0.33, 1, 0.68, 1)` | Enter / appear |
| `--sumi-ease-in` | `cubic-bezier(0.32, 0, 0.67, 0)` | Exit / leave |
| `--sumi-ease-in-out` | `cubic-bezier(0.65, 0, 0.35, 1)` | Symmetric transitions |
| `--sumi-ease-bounce` | `cubic-bezier(0.34, 1.56, 0.64, 1)` | Playful bounce |
| `--sumi-ease-spring` | `cubic-bezier(0.175, 0.885, 0.32, 1.1)` | Spring feel |
### Composite transition tokens
| Token | Animates |
|-------|----------|
| `--sumi-transition-colors` | color, background-color, border-color |
| `--sumi-transition-opacity` | opacity |
| `--sumi-transition-transform` | transform |
| `--sumi-transition-shadow` | box-shadow |
`prefers-reduced-motion: reduce` is respected globally — all durations collapse to near-zero.
---
## 8. Layout Shell
Full reference: [APP_SHELL.md](APP_SHELL.md).
| Token | Value | Role |
|-------|-------|------|
| `--sumi-header-height` | 56px | Header height |
| `--sumi-sidebar-width` | 240px | Sidebar expanded |
| `--sumi-sidebar-collapsed` | 64px | Sidebar collapsed |
| `--sumi-player-height` | 80px | Player bar |
| `--sumi-max-width` | 1400px | App max width |
| `--sumi-max-width-content` | 1200px | Content max width |
| `--sumi-max-width-narrow` | 800px | Narrow content |
| `--sumi-max-width-prose` | 65ch | Prose text width |
### Layout primitives (utility classes)
| Class | Token | Value |
|-------|-------|-------|
| `.max-w-layout-content` | `--layout-content-max-width` | 100rem |
| `.min-h-layout-main` | `--layout-main-min-height` | calc(100vh - 4rem) |
| `.min-h-layout-page` | `--layout-page-min-height` | 37.5rem |
| `.min-h-layout-page-sm` | `--layout-page-min-height-sm` | 25rem |
| `.min-h-layout-story` | `--layout-story-decorator-min-height` | 12rem |
Modal/drawer height constraints, lyrics, chat, and stream heights — all defined in `index.css` with matching utility classes (`.max-h-layout-modal`, `.h-layout-chat`, etc.). See `index.css` `@layer utilities` section for the full list.
---
## 9. Exceptions (arbitrary values)
Arbitrary Tailwind values (`w-[...]`, `h-[...]`, `rounded-[...]`, `shadow-[...]`) are **forbidden** unless:
- SVG/canvas rendering (e.g., `text-[2px]` for chart axes)
- Third-party component markup you don't control
- Documented here or in a PR with justification
Add `eslint-disable` comment when an exception is necessary.
See also: [.cursorrules](../.cursorrules) for layout primitives and spacing rules.

View file

@ -190,14 +190,14 @@ export default [js.configs.recommended, {
message: message:
'Use spacing scale classes (gap-0 through gap-24, p-0 through p-24, etc.) instead of arbitrary sizes. Valid scale values follow 4px base: 0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24. For exceptions, add eslint-disable comment.', 'Use spacing scale classes (gap-0 through gap-24, p-0 through p-24, etc.) instead of arbitrary sizes. Valid scale values follow 4px base: 0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24. For exceptions, add eslint-disable comment.',
}, },
// Colors: Prevent Tailwind default colors (use Kodo design system colors instead) // Colors: Prevent Tailwind default colors (use SUMI design system semantic tokens instead)
// Warn on default Tailwind color classes: slate, gray, zinc, neutral, stone, red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose // Warn on default Tailwind color classes: slate, gray, zinc, neutral, stone, red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose
// Allow: kodo-* colors, arbitrary values like text-[#fff], and color utilities without shades // Allow: semantic tokens (primary, secondary, destructive, success, warning, muted, etc.) and sumi-* tokens
{ {
selector: selector:
"Literal[value=/(text-|bg-|border-|ring-|outline-|divide-|placeholder-|from-|via-|to-|accent-|caret-|fill-|stroke-)(slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(50|100|200|300|400|500|600|700|800|900|950)/], TemplateElement[value.raw=/(text-|bg-|border-|ring-|outline-|divide-|placeholder-|from-|via-|to-|accent-|caret-|fill-|stroke-)(slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(50|100|200|300|400|500|600|700|800|900|950)/]", "Literal[value=/(text-|bg-|border-|ring-|outline-|divide-|placeholder-|from-|via-|to-|accent-|caret-|fill-|stroke-)(slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(50|100|200|300|400|500|600|700|800|900|950)/], TemplateElement[value.raw=/(text-|bg-|border-|ring-|outline-|divide-|placeholder-|from-|via-|to-|accent-|caret-|fill-|stroke-)(slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(50|100|200|300|400|500|600|700|800|900|950)/]",
message: message:
'Use Kodo design system colors (kodo-cyan, kodo-red, kodo-lime, kodo-steel, etc.) instead of Tailwind default colors. See apps/web/src/styles/COLOR_USAGE.md for color 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.',
}, },
// 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

View file

@ -4,7 +4,7 @@
* Note: Tailwind v4 uses CSS-first configuration via @theme directive. * Note: Tailwind v4 uses CSS-first configuration via @theme directive.
* Font size utilities (text-xs, text-sm, text-base, etc.) are automatically * Font size utilities (text-xs, text-sm, text-base, etc.) are automatically
* generated from CSS variables defined in: * generated from CSS variables defined in:
* - apps/web/src/styles/design-tokens.css (@theme block) * - apps/web/src/index.css (@theme inline block)
* *
* The following text size utilities are available: * The following text size utilities are available:
* - text-xs (0.75rem / 12px) * - text-xs (0.75rem / 12px)