Design & UI/UX Design System Composants UI

Design system : créer une bibliothèque de composants

Construisez un design system robuste : design tokens, composants réutilisables, documentation Storybook et gouvernance pour des interfaces cohérentes.

Benjamin Schweitzer Benjamin Schweitzer
Jeudi 8 mai 2025
4 min de lecture
Design system : créer une bibliothèque de composants

Pourquoi un design system change tout

Sans design system, chaque page d'un site devient un archipel : des boutons légèrement différents d'une section à l'autre, des espacements incohérents, des couleurs qui varient à chaque composant. Le design system est la réponse systématique à ce problème.

Un bon design system c'est : un langage commun entre designers et développeurs, une base de composants testés et accessibles, et une documentation vivante.

La pyramide d'un design system

          [Patterns]
       Connexions de formulaire
      Tableaux de données, cards
        
        [Composants]
    Button, Input, Modal, Toast
    Badge, Dropdown, Tabs, Alert

      [Fondations]
   Couleurs, Typographie, Espacement
   Ombres, Bordures, Animation, Icônes

    [Design Tokens]
 Variables nommées sémantiquement
 (connectées Figma ↔ Code)

Les design tokens — le lien Figma ↔ Code

Les tokens sont des variables nommées qui représentent les décisions de design :

// tokens.json (source de vérité)
{
  "color": {
    "primitive": {
      "blue-500": { "value": "#3b82f6" },
      "blue-600": { "value": "#2563eb" },
      "gray-100": { "value": "#f3f4f6" },
      "gray-900": { "value": "#111827" }
    },
    "semantic": {
      "primary": { "value": "{color.primitive.blue-500}" },
      "primary-hover": { "value": "{color.primitive.blue-600}" },
      "background": {
        "default": { "value": "#ffffff" },
        "subtle": { "value": "{color.primitive.gray-100}" }
      },
      "text": {
        "default": { "value": "{color.primitive.gray-900}" }
      }
    }
  },
  "spacing": {
    "xs": { "value": "4px" },
    "sm": { "value": "8px" },
    "md": { "value": "16px" },
    "lg": { "value": "24px" },
    "xl": { "value": "32px" },
    "2xl": { "value": "48px" }
  },
  "radius": {
    "sm": { "value": "4px" },
    "md": { "value": "8px" },
    "lg": { "value": "12px" }
  }
}

Avec Style Dictionary, transformez ces tokens en variables CSS, SCSS, ou JS :

npm install -D style-dictionary

// build-tokens.js
const StyleDictionary = require('style-dictionary');

StyleDictionary.extend({
  source: ['tokens.json'],
  platforms: {
    css: {
      transformGroup: 'css',
      files: [{
        destination: 'tokens.css',
        format: 'css/variables',
        options: { outputReferences: true }
      }]
    }
  }
}).buildAllPlatforms();

Résultat :

:root {
  --color-primitive-blue-500: #3b82f6;
  --color-semantic-primary: var(--color-primitive-blue-500);
  --spacing-md: 16px;
  --radius-md: 8px;
}

Construire un composant Button robuste

<!-- HTML sémantique avec variantes par attributs data -->
<button 
  class="btn"
  data-variant="primary"
  data-size="md"
  type="button">
  <span class="btn-icon btn-icon-left" aria-hidden="true">
    <svg>...</svg>
  </span>
  <span class="btn-label">Envoyer</span>
</button>

.btn {
  /* Structure */
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-xs);
  border: 2px solid transparent;
  cursor: pointer;
  font-weight: 600;
  transition: background 150ms, border-color 150ms, color 150ms;

  /* Focus accessible */
  outline: none;
}
.btn:focus-visible {
  box-shadow: 0 0 0 3px var(--color-semantic-primary), 
              0 0 0 5px rgba(59,130,246,0.3);
}

/* Tailles */
.btn[data-size="sm"] { padding: 6px 14px; font-size: 13px; border-radius: var(--radius-sm); }
.btn[data-size="md"] { padding: 10px 20px; font-size: 14px; border-radius: var(--radius-md); }
.btn[data-size="lg"] { padding: 14px 28px; font-size: 16px; border-radius: var(--radius-md); }

/* Variantes */
.btn[data-variant="primary"] {
  background: var(--color-semantic-primary);
  color: white;
}
.btn[data-variant="primary"]:hover { 
  background: var(--color-semantic-primary-hover);
}
.btn[data-variant="secondary"] {
  background: transparent;
  border-color: var(--color-semantic-primary);
  color: var(--color-semantic-primary);
}
.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}

Documentation avec Storybook

Storybook est le standard pour documenter les composants de façon interactive :

npx storybook@latest init

// Button.stories.js
export default {
  title: 'Composants/Button',
  component: Button,
  parameters: {
    docs: { description: { component: 'Bouton principal. Utiliser pour les CTAs primaires.' } }
  },
  argTypes: {
    variant: { control: 'select', options: ['primary', 'secondary', 'danger'] },
    size: { control: 'select', options: ['sm', 'md', 'lg'] },
    disabled: { control: 'boolean' }
  }
};

export const Primary = { args: { variant: 'primary', label: 'Envoyer' } };
export const Secondary = { args: { variant: 'secondary', label: 'Annuler' } };
export const Loading = { args: { variant: 'primary', loading: true, label: 'Chargement...' } };

Gouvernance et évolution

Un design system qui n'évolue pas meurt. Définissez dès le départ :

Processus de contribution :

  1. Besoin identifié → issue dans le repo du design system
  2. Discussion en équipe (est-ce vraiment un composant générique ?)
  3. Maquette Figma + code en parallèle
  4. Review croisée designer/développeur
  5. Documentation + Storybook story
  6. Release avec changelog
Versioning sémantique :
  • PATCH (1.0.x) : correction de bugs, micro-ajustements
  • MINOR (1.x.0) : nouveau composant ou variante, rétro-compatible
  • MAJOR (x.0.0) : breaking change (renommage de token, API de composant)

Pour aller plus loin : Design Systems Handbook — référence gratuite de InVision.

Un design system vivant, pas un musée

Le plus grand risque d'un design system est de devenir obsolète. Prévoyez des sessions de revue trimestrielles, maintenez un changelog visible, et formez les nouveaux arrivants dès le premier jour. Un design system adopté activement divise le temps d'intégration par deux sur la durée.

Cet article vous a plu ?

Donnez-lui une note, ça m'aide vraiment !

Partager l'article