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
- JAMAIS de couleur en dur dans un composant → toujours
var(--token) - Accent unique pour toute l'interaction (hover, focus, active states)
- Surface hierarchy : --bg → --surface → --surface-2 (profondeur croissante)
- Text hierarchy : --text (titres) → --text-2 (descriptions) → --text-3 (labels, meta)
- 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