Explorer
KNOW-PAT-111

Web UI/UX - Dark Theme CSS Variables Design System : accent, surface hierarchy, text tokens

Domaine
web-uiux
Type
pattern
Priorité
P0

Parent : [[INDEX-WEB-UIUX]]

Web UI/UX - Dark Theme CSS Variables Design System : accent, surface hierarchy, text tokens

Problème

Une IA génère du CSS en dur dans chaque composant (style={{ background: '#111' }}), créant un chaos de couleres inconsistantes, aucune hiérarchie visuelle, et impossible à maintenir.

Solution

Système de design complet basé sur des variables CSS :root, avec 4 niveaux de surface, 3 niveaux de texte, et 1 accent unique. AUCUNE couleur hexadécimale n'est utilisée directement dans les composants React.

:root {
  --accent: #e5191a;
  --accent-dim: rgba(229, 25, 26, 0.12);
  --accent-hover: #ff2d2e;
  
  --bg: #0a0b0d;         /* Niveau 0 : fond global */
  --surface: #111318;    /* Niveau 1 : cartes, panels */
  --surface-2: #16181f;  /* Niveau 2 : hover, sub-panels */
  
  --border: #1e2028;     /* Bordure par défaut */
  --border-hover: #2a2d3a; /* Bordure hover/active */
  
  --text: #f0f1f5;       /* Texte principal */
  --text-2: #8b8fa8;     /* Texte secondaire */
  --text-3: #4a4e63;     /* Texte muted, labels */
}

/* Utilities réutilisables */
.surface {
  background: var(--surface);
  border: 1px solid var(--border);
}

/* Scrollbar stylisée */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: var(--surface); }
::-webkit-scrollbar-thumb { background: #2a2d3a; border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--accent); }

::selection {
  background: rgba(229, 25, 26, 0.25);
  color: #fff;
}

Règles d'or

  1. JAMAIS de couleur en dur dans un composant → toujours var(--token)
  2. Accent unique pour toute l'interaction (hover, focus, active states)
  3. Surface hierarchy : --bg → --surface → --surface-2 (profondeur croissante)
  4. Text hierarchy : --text (titres) → --text-2 (descriptions) → --text-3 (labels, meta)
  5. Borders : --border (défaut) → --border-hover (hover/active)

Exemple d'utilisation correcte

// ✅ CORRECT : utilise les tokens
<div style={{ background: 'var(--surface)', border: '1px solid var(--border)' }}>
  <h1 style={{ color: 'var(--text)' }}>Titre</h1>
  <p style={{ color: 'var(--text-2)' }}>Description</p>
  <button style={{ background: 'var(--accent)', color: '#fff' }}>Action</button>
</div>

Exemple incorrect

// ❌ INCORRECT : couleurs en dur partout
<div style={{ background: '#1a1a1a', border: '1px solid #333' }}>
  <h1 style={{ color: 'white' }}>Titre</h1>
  <p style={{ color: '#888' }}>Description</p>
  <button style={{ background: 'red' }}>Action</button>
</div>

Pourquoi

  • Cohérence : impossible d'avoir 47 nuances de gris différentes
  • Maintenabilité : changer l'accent change TOUT le site
  • Dark mode natif : pas besoin de classe .dark, le :root suffit
  • Accessibilité : ratios de contraste fixes et testables

Quand l'utiliser

  • Tout nouveau projet web
  • Refonte UI existante
  • Design system partagé entre plusieurs applis

Quand NE PAS l'utiliser

  • Prototype jetable (1 page, 1 jour)
  • Thème clair uniquement (adapter les tokens)

Références

  • ProjectAlpha/globals.css L1-15