Architecture de Design System en pratique : Le parcours complet de construction des Design Tokens aux bibliothèques de composants
L'Architecture à Trois Couches des Design Systems
┌─────────────────────────────────┐
│ Couche Composants │ Button, Card, Modal...
├─────────────────────────────────┤
│ Couche Motifs │ Formulaires, Navigation, Tableaux de données
├─────────────────────────────────┤
│ Couche Tokens (Design Tokens) │ Couleurs, Espacement, Tailles de police, Ombres
└─────────────────────────────────┘
Les tokens sont la fondation, les motifs sont la composition, les composants sont le point d'arrivée. Construire de bas en haut, consommer de haut en bas.
Le Système de Design Tokens
1. Tokens de Couleur
/* Tokens sémantiques à trois couches */
/* Couche 1 : Valeurs primitives */
:root {
--blue-50: #eff6ff;
--blue-500: #3b82f6;
--blue-700: #1d4ed8;
--gray-50: #f9fafb;
--gray-900: #111827;
--red-500: #ef4444;
--green-500: #22c55e;
}
/* Couche 2 : Mapping sémantique */
:root {
--color-primary: var(--blue-500);
--color-primary-hover: var(--blue-700);
--color-surface: var(--gray-50);
--color-text: var(--gray-900);
--color-danger: var(--red-500);
--color-success: var(--green-500);
}
/* Couche 3 : Spécifique au composant */
:root {
--button-bg: var(--color-primary);
--button-bg-hover: var(--color-primary-hover);
--button-text: white;
--input-border: var(--color-border);
--input-border-focus: var(--color-primary);
}
2. Tokens d'Espacement (Système de grille 8pt)
:root {
--space-0: 0;
--space-1: 0.25rem; /* 4px */
--space-2: 0.5rem; /* 8px */
--space-3: 0.75rem; /* 12px */
--space-4: 1rem; /* 16px */
--space-5: 1.5rem; /* 24px */
--space-6: 2rem; /* 32px */
--space-8: 3rem; /* 48px */
--space-10: 4rem; /* 64px */
}
3. Tokens de Typographie
:root {
/* Tailles de police */
--text-xs: 0.75rem; /* 12px */
--text-sm: 0.875rem; /* 14px */
--text-base: 1rem; /* 16px */
--text-lg: 1.125rem; /* 18px */
--text-xl: 1.25rem; /* 20px */
--text-2xl: 1.5rem; /* 24px */
--text-3xl: 1.875rem; /* 30px */
/* Hauteurs de ligne */
--leading-tight: 1.25;
--leading-normal: 1.5;
--leading-relaxed: 1.75;
/* Graisses de police */
--font-normal: 400;
--font-medium: 500;
--font-semibold: 600;
--font-bold: 700;
}
4. Tokens d'Ombre
:root {
--shadow-xs: 0 1px 2px rgba(0,0,0,0.05);
--shadow-sm: 0 1px 3px rgba(0,0,0,0.1), 0 1px 2px rgba(0,0,0,0.06);
--shadow-md: 0 4px 6px rgba(0,0,0,0.07), 0 2px 4px rgba(0,0,0,0.06);
--shadow-lg: 0 10px 15px rgba(0,0,0,0.1), 0 4px 6px rgba(0,0,0,0.05);
--shadow-xl: 0 20px 25px rgba(0,0,0,0.1), 0 8px 10px rgba(0,0,0,0.04);
}
Mécanisme de Changement de Thème
Approche par Variables CSS
/* Thème clair (par défaut) */
:root {
--color-surface: #ffffff;
--color-text: #111827;
--color-border: #e5e7eb;
--color-primary: #3b82f6;
}
/* Thème sombre */
[data-theme="dark"] {
--color-surface: #1f2937;
--color-text: #f9fafb;
--color-border: #374151;
--color-primary: #60a5fa;
}
/* Thème à contraste élevé */
[data-theme="high-contrast"] {
--color-surface: #000000;
--color-text: #ffffff;
--color-border: #ffffff;
--color-primary: #ffff00;
}
Changement de Thème en React
import { useEffect, useState } from 'react';
type Theme = 'light' | 'dark' | 'system';
function useTheme() {
const [theme, setTheme] = useState<Theme>(() => {
return (localStorage.getItem('theme') as Theme) || 'system';
});
useEffect(() => {
const root = document.documentElement;
const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const resolved = theme === 'system' ? (systemDark ? 'dark' : 'light') : theme;
root.setAttribute('data-theme', resolved);
localStorage.setItem('theme', theme);
}, [theme]);
return { theme, setTheme };
}
Mode Sombre avec Tailwind CSS v4
/* tailwind.config.ts en mode variables CSS */
@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));
<!-- Auto-responsive au thème -->
<div class="bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100">
Le contenu s'adapte automatiquement au thème actuel
</div>
Principes de Conception d'API de Composants
1. Responsabilité Unique + Composition d'Abord
// ❌ Sur-encapsulation : Toutes les fonctionnalités fourrées dans un composant
<SuperButton variant="primary" size="lg" icon="save" loading disabled />
// ✅ Pattern de composition : Assembler via des composants enfants
<Button variant="primary" size="lg">
<Icon name="save" />
<Button.Label>Enregistrer</Button.Label>
<Button.Loading />
</Button>
2. Contrôlé vs Non Contrôlé
// Mode contrôlé : État géré externement
<Input value={value} onChange={setValue} />
// Mode non contrôlé : État géré en interne par le composant
<Input defaultValue="hello" onChange={handleChange} />
// Compatible avec les deux
interface InputProps {
value?: string; // Contrôlé
defaultValue?: string; // Non contrôlé
onChange?: (value: string) => void;
}
3. Composants Polymorphes
// Button peut s'afficher comme button, a, ou Link de Next.js
type ButtonProps<C extends React.ElementType = 'button'> = {
as?: C;
} & React.ComponentPropsWithoutRef<C>;
function Button<C extends React.ElementType = 'button'>(
{ as, ...props }: ButtonProps<C>
) {
const Component = as || 'button';
return <Component className="btn" {...props} />;
}
// Utilisation
<Button>Cliquer</Button>
<Button as="a" href="/link">Lien</Button>
<Button as={Link} to="/page">Lien de route</Button>
4. Pattern Slots
// Design Slots du composant Card
interface CardSlots {
header?: React.ReactNode;
media?: React.ReactNode;
content: React.ReactNode;
footer?: React.ReactNode;
actions?: React.ReactNode;
}
function Card({ header, media, content, footer, actions }: CardSlots) {
return (
<div className="card">
{header && <div className="card-header">{header}</div>}
{media && <div className="card-media">{media}</div>}
<div className="card-content">{content}</div>
{footer && <div className="card-footer">{footer}</div>}
{actions && <div className="card-actions">{actions}</div>}
</div>
);
}
Adaptation Multi-Marque
Couche de Surcharge de Marque
/* Tokens de base (Marque A) */
:root {
--brand-primary: #3b82f6;
--brand-radius: 8px;
--brand-font: 'Inter', sans-serif;
}
/* Surcharge Marque B */
[data-brand="b"] {
--brand-primary: #8b5cf6;
--brand-radius: 12px;
--brand-font: 'Poppins', sans-serif;
}
/* Surcharge Marque C */
[data-brand="c"] {
--brand-primary: #f59e0b;
--brand-radius: 4px;
--brand-font: 'Roboto', sans-serif;
}
Pipeline de Compilation des Tokens
Fichiers sources de design (Figma)
↓
Compilation Style Dictionary
↓
├── Variables CSS (Web)
├── Configuration Tailwind (Projets Tailwind)
├── Fichiers Swift iOS
├── Fichiers Kotlin Android
└── JSON (Site de documentation)
// style-dictionary.config.js
const StyleDictionary = require('style-dictionary');
module.exports = {
source: ['tokens/**/*.json'],
platforms: {
css: {
transformGroup: 'css',
buildPath: 'dist/css/',
files: [{ destination: 'variables.css', format: 'css/variables' }],
},
tailwind: {
transformGroup: 'js',
buildPath: 'dist/tailwind/',
files: [{ destination: 'theme.js', format: 'javascript/module' }],
},
},
};
Pratiques du Design System de ToolsKu
ToolsKu utilise Tailwind CSS v4 + variables CSS pour construire son design system :
/* Tokens de thème ToolsKu */
:root {
--color-primary: #2563eb;
--color-surface: #ffffff;
--color-text: #1f2937;
--radius: 8px;
--font-sans: 'Inter', system-ui, sans-serif;
}
/* Composant carte d'outil */
.tool-card {
padding: var(--space-4);
border-radius: var(--radius);
background: var(--color-surface);
border: 1px solid var(--color-border);
transition: transform 0.2s, box-shadow 0.2s;
}
.tool-card:hover {
transform: translateY(-2px);
box-shadow: var(--shadow-md);
}
Gouvernance du Design System
Gestion des Versions
@toolsku/tokens v2.4.0 → Package Design Tokens
@toolsku/components v3.1.0 → Bibliothèque de composants
@toolsku/patterns v1.2.0 → Bibliothèque de motifs
Chaîne de dépendances : patterns → components → tokens
Workflow de Changement
1. Le designer modifie les tokens dans Figma
2. Auto-synchronisation vers le dépôt Git (Plugin Figma)
3. CI exécute la compilation Style Dictionary
4. Tests de régression visuelle (Chromatic/Storybook)
5. Auto-publication de la nouvelle version (Changesets)
Site de Documentation
Storybook
├── Tokens → Vitrine couleurs, espacement, tailles de police
├── Components → Documentation d'interaction des composants
├── Patterns → Guide d'utilisation des motifs
└── Guidelines → Documentation des spécifications de design
Résumé
Un design system n'est pas seulement une bibliothèque de composants, mais une architecture complète des Tokens aux Composants aux Motifs. Les tokens à trois couches (Primitif → Sémantique → Composant) sont le fondement de l'évolutivité. Les patterns de composition surpassent la sur-encapsulation, et les variables CSS + Tailwind est le choix technologique le plus pratique en 2026. Rappelez-vous : un bon design system permet aux designers et développeurs de parler le même langage, et les tokens sont le vocabulaire de ce langage.
Essayez ces outils exécutés localement dans le navigateur — aucune inscription requise →