veza/apps/web/docs/DESIGN_TOKENS.md
senke 4b9d0a341d ui(design): migrate ImageCropper, PlaybackSummary to layout tokens
- ImageCropper: h-[80vh] → h-layout-modal-sm (80vh)
- PlaybackSummary: h-[200px] → min-h-50 (scale Tailwind)
- Add h-layout-modal-sm utility class

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-10 14:07:19 +01:00

134 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Design Tokens — Référence
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.
## 1. Espacements (layout et sections)
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) |
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.
## 2. Couleurs
- **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).
Ne pas utiliser les couleurs par défaut Tailwind (slate, gray, zinc, etc.) ; privilégier les tokens Kodo (kodo-void, kodo-cyan, etc.).
## 3. Typographie
Échelle Tailwind utilisée (tailles de texte) :
| 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 |
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).
### Classes utilitaires typographiques (index.css `@layer utilities`)
| 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 |
Utiliser ces classes en priorité pour les headings et body text. Ajouter `font-display` séparément si la police Orbitron est souhaitée.
### Hiérarchie visuelle (usage recommandé)
| 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 |
Contraste : privilégier `text-foreground` pour linfo principale et `text-muted-foreground` pour linfo secondaire (style Spotify : titre + artiste, description en gris).
### Exceptions (tailles arbitraires typo)
- **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`).
## 4. Ombres
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`) |
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`).
## 5. Layout shell (sidebar, header, main)
Définis dans [index.css](../src/index.css). Référence complète : [APP_SHELL.md](APP_SHELL.md).
- **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.
Ne pas définir de variables concurrentes (ex. `--sidebar-width`, `--header-height`) ailleurs ; index.css est la source unique pour le shell.
## 6. Transitions et animations
Définies dans [design-system.css](../src/styles/design-system.css).
| 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 |
Utiliser ces variables dans les transitions (ex. `transition-all var(--duration-normal) var(--ease-out)`).
## 7. Exceptions (valeurs arbitraires)
Les règles ESLint interdisent les classes arbitraires pour `w-[...]`, `h-[...]`, `rounded-[...]`, `shadow-[...]`, etc. Exceptions autorisées avec commentaire `eslint-disable` :
- 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).