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 { handlers } from '../src/mocks/handlers';
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 React from 'react';
import { StorybookDecorator } from './decorators';
@ -68,9 +65,9 @@ const preview: Preview = {
backgrounds: {
default: 'dark',
values: [
{ name: 'dark', value: '#121212' },
{ name: 'light', value: '#ffffff' },
{ name: 'steel', value: '#1a1a2e' },
{ name: 'dark', value: '#121215' },
{ name: 'light', value: '#faf9f6' },
{ name: 'raised', value: '#1a1a1f' },
],
},
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
- **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`), dont le bord gauche suit la sidebar (expanded/collapsed).
- **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.
- **Player** : barre de lecture fixe en bas (rendue par `GlobalPlayer` dans `DashboardLayout`).
- **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).
- **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. Espacement interne via tokens SUMI (`--sumi-space-*`).
- **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 :
- [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 |
|----------|--------|------|
| `--header-height` | 4rem | Hauteur de la barre header fixe |
| `--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-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 |
@ -32,7 +63,7 @@ Les largeurs sidebar sont définies à part : `--sidebar-width-expanded` (15rem)
## 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 |
|--------|-----------|--------|
@ -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 |
| `.left-header-expanded` | left | Barre header quand sidebar ouverte |
| `.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`).
## 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
- **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 |
|------------|---------|----------------------|
| 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. |
| 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
- 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`.
- 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
**Purpose**: Define the "Surgical Minimalism" design philosophy for the Veza application
**Purpose**: Define the SUMI design philosophy for the Veza application
## Overview
"Surgical Minimalism" is a design philosophy that emphasizes:
- **Purposeful design**: Every visual element serves a function
- **Increased whitespace**: More breathing room improves readability and hierarchy
- **Restrained color usage**: Color used strategically, not decoratively
- **Subtle interactions**: Hover effects and animations are functional, not excessive
- **Visual clarity**: Remove unnecessary decorative elements
SUMI is a design philosophy rooted in the **sumi-e** (墨絵) ink wash painting tradition. The guiding motto is:
> **« Encre, pas néon »** — Ink, not neon.
Three pillars:
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
### 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
- **20% Color**: Strategic use of `kodo-cyan` for primary actions only, sparing use of other accent colors
- **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`).
- **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**:
- Primary actions: Use `kodo-cyan` (buttons, active states, focus rings)
- Secondary actions: Use `kodo-steel` instead of cyan
- Decorative elements: Use neutral colors, avoid color backgrounds
- Status/info: Use semantic colors only when necessary
- Primary actions: `--sumi-accent` (buttons, active states, focus rings)
- Secondary actions: `--sumi-bg-hover` / `--sumi-border-default`
- Semantic: `--sumi-success` (sage), `--sumi-warning` (gold), `--sumi-error` (vermillion)
- 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**:
- **Card padding**: 32px (was 24px) - `p-8` instead of `p-6`
- **Section spacing**: 32px standard (was 24px) - `space-y-8` instead of `space-y-6`
- **Large sections**: 48px for major containers - `space-y-12` for DashboardPage
- **8px grid alignment**: All spacing values align to 8px multiples
**Hierarchy**:
- Headings: `--sumi-text-primary` + `--sumi-font-heading` + `--sumi-weight-semibold`
- Body: `--sumi-text-primary` + `--sumi-font-body` + `--sumi-weight-regular`
- Secondary/metadata: `--sumi-text-secondary` or `--sumi-text-tertiary`, sparingly
**Benefits**:
- Improved readability
- Better visual hierarchy
- Reduced visual clutter
- More professional appearance
### 4. Whitespace & Readability
### 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):
- Background color changes: `hover:bg-white/5` for interactive feedback
**Layout gaps**:
- `--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)
- Border color changes: `hover:border-white/10` for interactive elements
- Text color changes: `hover:text-white` for navigation links
- Border color changes: `hover:border-[var(--sumi-border-strong)]`
- 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):
- Scale transforms: `hover:scale-[1.02]`, `hover:scale-110` on cards
- Decorative shadows: `hover:shadow-neon-cyan/20`, `hover:shadow-lg` on cards
- Image zoom effects: `group-hover:scale-110` on decorative images
- Multiple simultaneous effects: Scale + shadow + border combinations
**Anti-patterns** (NEVER do):
- ❌ Scale transforms on hover: no `hover:scale-[1.02]`, `hover:scale-105`, `hover:scale-110`
- ❌ Neon glows: no `shadow-[0_0_15px_rgba(0,255,255,...)]`, no `shadow-neon-*`
- ❌ Decorative animations: no pulsing, no bouncing, no breathing effects for aesthetics
- ❌ 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**:
- 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)
**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.
**Remove Gradients**:
- Card backgrounds: Use solid colors (`bg-kodo-ink`, `bg-kodo-graphite`)
- Decorative sections: Replace with solid backgrounds
- Hover overlays: Use solid colors with opacity
### 7. Gradients: Functional Only
**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):
- `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
Sub-themes are **contextual accent overrides**, not global theme replacements. They provide feature-specific color accents while the core SUMI palette stays constant.
**Avoid** (not 8px-aligned):
- `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
- `gap-10`, `p-10`, `m-10` (40px) - Use `gap-8` or `gap-12` instead
- `gap-20`, `p-20`, `m-20` (80px) - Use `gap-16` or `gap-24` instead
| Sub-theme | Accent | Token | Context |
|-----------|--------|-------|---------|
| Nature | Sakura pink | `--sakura: #e0a0b8` | Nature/ambient content |
| Graffiti | Magenta | `--graffiti-magenta: #c840a0` | Urban/graffiti features |
| 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**:
- Main content: `text-white` (was `text-kodo-text-main` with beige)
- Headings: `text-white`
- Interactive elements: `text-white` with opacity for hover states
These patterns contradict SUMI and must be avoided:
**Secondary Text**:
- Truly secondary info: `text-kodo-secondary` or `text-white opacity-80`
- Metadata: `text-kodo-content-dim`
- Use sparingly: Only for information that is genuinely less important
**Result**: Better contrast, improved readability, WCAG AA compliant
## Design Tokens
### 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`
| Anti-pattern | Why | Alternative |
|--------------|-----|-------------|
| `hover:scale-[1.02]` | Decorative, not functional | `hover:bg-[var(--sumi-bg-hover)]` |
| `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` |
| `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` |
| `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 |
## 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)
- [ ] Primary buttons use `bg-kodo-cyan` (not outline/secondary buttons)
- [ ] Active navigation states use `text-kodo-cyan` or `bg-kodo-cyan/10`
- [ ] Focus rings use `focus-visible:ring-kodo-cyan`
- [ ] Critical status indicators use cyan appropriately
- [ ] No cyan on decorative elements or backgrounds
### Spacing & Layout
- [ ] Spacing uses SUMI scale (`--sumi-space-*`) or Tailwind equivalents
- [ ] Layout uses SUMI layout tokens (`--sumi-max-width`, `--sumi-header-height`, etc.)
- [ ] Generous whitespace between sections
#### Secondary Actions (Use Steel)
- [ ] Outline buttons use `border-kodo-steel` (not `border-kodo-cyan`)
- [ ] Outline button hover states use `hover:border-kodo-steel/50` (not cyan)
- [ ] Secondary navigation items use `text-kodo-steel` (not cyan)
- [ ] Non-primary interactive elements use steel colors
- [ ] Icon buttons (non-primary) use steel, not cyan
### Interactions
- [ ] Hover effects are subtle: background/opacity/border color only
- [ ] No scale transforms on interactive elements
- [ ] No decorative shadows or glows on hover
- [ ] Transitions use `--sumi-duration-fast` / `--sumi-ease-default`
#### Neutral Backgrounds
- [ ] Cards use `bg-kodo-graphite` or `bg-kodo-ink` (solid colors, no gradients)
- [ ] Elevated surfaces use `bg-kodo-ink`
- [ ] Main backgrounds use `bg-kodo-void`
- [ ] No decorative color backgrounds (use neutral colors)
### Typography
- [ ] Body text uses `--sumi-font-body` (Inter)
- [ ] Headings use `--sumi-font-heading` (Space Grotesk)
- [ ] Text sizes follow SUMI scale (`--sumi-text-*`)
- [ ] Text contrast meets WCAG AA
#### Color Ratio Check
- [ ] Approximately 80% of the component uses neutral colors (void, ink, graphite, steel, white)
- [ ] Approximately 20% uses accent colors (cyan for primary actions only)
- [ ] No excessive color usage that breaks the 80/20 rule
### Glass & Elevation
- [ ] Glass surfaces use `--sumi-glass-bg` + `backdrop-blur`
- [ ] Shadows use SUMI scale (`--sumi-shadow-*`)
- [ ] Focus rings use `--sumi-shadow-glow`
### Spacing (8px Grid Alignment)
#### Grid Alignment
- [ ] All spacing values are multiples of 8px (0, 8, 16, 24, 32, 48, 64, 96px)
- [ ] 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
### Theme Compatibility
- [ ] Component works with `[data-theme="dark"]` and `[data-theme="light"]`
- [ ] No hardcoded colors that break in light theme
- [ ] Borders use `--sumi-border-*` tokens
## Examples
### ✅ Good: Surgical Minimalism Applied
### ✅ Good: SUMI Applied
```tsx
// Card with solid background, subtle hover, adequate padding
<Card className="p-8 hover:bg-white/5 transition-colors">
// Card with SUMI tokens
<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>
<CardTitle className="text-white">Title</CardTitle>
<CardTitle className="text-[var(--sumi-text-primary)] font-heading">Title</CardTitle>
</CardHeader>
<CardContent>
<p className="text-white opacity-80">Content</p>
<p className="text-[var(--sumi-text-secondary)]">Content</p>
</CardContent>
</Card>
// Button with cyan only for primary actions
<Button variant="default" className="bg-kodo-cyan">Primary Action</Button>
<Button variant="outline" className="border-kodo-steel hover:border-kodo-steel/50">
// Button with SUMI accent
<Button className="bg-[var(--sumi-accent)] text-[var(--sumi-text-inverse)]">
Primary Action
</Button>
<Button variant="outline" className="border-[var(--sumi-border-default)]
hover:border-[var(--sumi-border-strong)]">
Secondary Action
</Button>
// Section with proper spacing
<div className="space-y-8">
<Section1 />
<Section2 />
</div>
```
### ❌ Avoid: Excessive Decoration
### ❌ Avoid: Anti-SUMI Patterns
```tsx
// Card with gradient, scale transform, decorative shadow
<Card className="p-6 bg-gradient-to-r from-kodo-ink to-kodo-graphite hover:scale-[1.02] hover:shadow-neon-cyan/20">
{/* Avoid */}
// Neon glow + scale transform + gradient
<Card className="bg-gradient-to-r from-kodo-ink to-kodo-graphite
hover:scale-[1.02] hover:shadow-neon-cyan/20">
{/* ❌ Gradient bg, scale, neon glow */}
</Card>
// Button with cyan for secondary actions
<Button variant="outline" className="border-kodo-cyan hover:border-kodo-cyan/50">
{/* Should use kodo-steel */}
// Kodo tokens (deprecated)
<Button className="bg-kodo-cyan text-black">
{/* ❌ Use --sumi-accent instead */}
</Button>
// Section with insufficient spacing
<div className="space-y-4">
{/* Should be space-y-8 */}
// Decorative animation
<div className="animate-pulse bg-cyan-500/20">
{/* ❌ Neon color + decorative animation */}
</div>
```
## Migration Path
### Completed Actions
1. ✅ **Text Colors**: Changed primary text to white, use dim text sparingly
2. ✅ **Card Padding**: Increased from 24px to 32px
3. ✅ **Section Spacing**: Increased from 24px to 32px (standard), 48px (large)
4. ✅ **Hover Effects**: Removed excessive scale transforms and decorative shadows
5. ✅ **Gradients**: Removed from cards, kept only in hero sections
6. ✅ **8px Grid**: Documented and verified alignment
### Completed
1. ✅ SUMI token system defined in `index.css` (`:root` + `[data-theme="light"]`)
2. ✅ Theme switching migrated from class to `[data-theme]` attribute
3. ✅ Typography tokens: Inter (body) + Space Grotesk (headings) + JetBrains Mono (code)
4. ✅ Glass effects on header and player bar
5. ✅ Shadow and z-index scales defined
6. ✅ Contextual accent tokens (graffiti, gaming, terminal, sakura)
### In Progress
- **Color Reduction**: Audit complete, replacement in progress
- **Component Updates**: Applying principles to remaining components
- Component migration from `kodo-*` tokens to `--sumi-*` tokens
- Audit and removal of remaining neon glows and scale transforms
- Light theme (Washi Paper) refinement
### Future Work
- Apply to all remaining pages and components
- Create design system components that enforce principles
- Add linting rules to prevent violations
- Enforce SUMI tokens via linting rules
- Paper grain texture as optional background layer
- Ink wash gradient presets for hero/feature sections
- Sub-theme contextual scoping
## References
- **8px Grid System**: `apps/web/src/styles/GRID_SYSTEM.md`
- **Cyan Usage Audit**: `apps/web/docs/CYAN_USAGE_AUDIT.md`
- **Hover Effects Audit**: `apps/web/docs/HOVER_EFFECTS_AUDIT.md`
- **Gradient Usage Verification**: `apps/web/docs/GRADIENT_USAGE_VERIFICATION.md`
- **Section Spacing Audit**: `apps/web/docs/SECTION_SPACING_AUDIT.md`
- **Design Tokens**: `apps/web/src/styles/design-tokens.css`
- **SUMI tokens source**: `apps/web/src/index.css``:root` and `[data-theme="light"]`
- **App Shell layout**: `apps/web/docs/APP_SHELL.md`
- **Design Tokens doc**: `apps/web/docs/DESIGN_TOKENS.md`
- **Storybook contract**: `apps/web/docs/STORYBOOK_CONTRACT.md`
## Benefits
**User Experience**:
- Reduced cognitive load
- Improved readability
- Better visual hierarchy
- More professional appearance
- Faster information processing
- Reduced cognitive load — warm neutrals are easier on the eyes
- Improved readability — high contrast text, generous whitespace
- Better visual hierarchy — depth through layers, not decoration
- Professional, distinctive aesthetic — ink wash, not neon
**Developer Experience**:
- Clear design principles
- Consistent patterns
- Reusable utilities
- Easier maintenance
- Better scalability
- Single token system (`--sumi-*`) — no ambiguity between old/new tokens
- Clear anti-patterns — easy to audit and enforce
- Consistent patterns across dark and light themes
- Meaningful names tied to the sumi-e metaphor
**Accessibility**:
- WCAG AA compliant contrast ratios
- Clear focus states
- Reduced visual noise
- Better screen reader experience
- Clear focus states (`--sumi-shadow-glow`)
- Reduced visual noise and motion
- 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 |
|----------|--------|------|
| `--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) |
## 1. Colors
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.
- **Sidebar** : `--sidebar`, `--sidebar-foreground`, `--sidebar-primary`, etc. (index.css).
- **Mapping et usage** : [src/styles/COLOR_USAGE.md](../src/styles/COLOR_USAGE.md).
### Surfaces
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 |
|--------|--------------|--------|
| `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 |
### Borders
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 |
|--------|------------|-------|
| `.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 |
4 pigments provide all accent color needs:
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 |
|------|--------|----------|
| 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 |
### Semantic aliases
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.
- **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`).
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.
## 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 |
|----------|------|
| `--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`) |
## 2. Typography
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`.
- **Header** : `--header-height`, `--header-left-expanded`, `--header-left-collapsed`.
- **Main** : `--main-offset-top`, `--main-offset-bottom`, `--main-margin-left-expanded`, `--main-margin-left-collapsed`.
- **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`.
- **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`.
- **Lyrics / hero** : `--layout-lyrics-height` (60vh), `--layout-lyrics-height-sm` (50vh) — classes `.h-layout-lyrics`, `.h-layout-lyrics-sm`.
- **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`.
- **Modal hauteur fixe** : `--layout-modal-max-height-sm` (80vh) — classe `.h-layout-modal-sm` pour modales type cropper.
| Token | Size | Tailwind class |
|-------|------|----------------|
| `--sumi-text-4xl` | 2.25rem | `text-4xl` |
| `--sumi-text-3xl` | 1.875rem | `text-3xl` |
| `--sumi-text-2xl` | 1.5rem | `text-2xl` |
| `--sumi-text-xl` | 1.25rem | `text-xl` |
| `--sumi-text-lg` | 1.125rem | `text-lg` |
| `--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 |
|----------|--------|--------|
| `--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 |
`.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.
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:
'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
// 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:
"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:
'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)
// 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.
* Font size utilities (text-xs, text-sm, text-base, etc.) are automatically
* 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:
* - text-xs (0.75rem / 12px)