Une équipe crée un composant Card pour harmoniser trois pages. Six mois plus tard, il possède vingt-sept propriétés : orientation, densité, badge, icône, menu, prix, progression, sélection, chargement et permissions. Chaque nouveau besoin ajoute un booléen. Deux combinaisons seulement sont réellement testées ; une modification d’espacement casse l’espace client mais corrige le catalogue.
Le problème vient moins du sur-mesure que du niveau d’abstraction. Le composant essaie de représenter une carte visuelle, un résultat de recherche, une commande et une action métier. À l’opposé, laisser chaque produit reconstruire boutons, formulaires et modales disperse accessibilité, comportement et dette. Standardiser trop tôt fige les hypothèses ; trop tard, les incohérences deviennent coûteuses à retirer.
Le vrai enjeu est de stabiliser les invariants et de laisser varier le métier. Une primitive possède comportement et accessibilité. Un composant porte une intention d’interface. Un pattern organise plusieurs éléments. Une feature orchestre données, droits et effets. Leur contrat, leur owner et leur cycle de version ne sont pas identiques.
Dans une démarche de développement web sur mesure, le design system devient une infrastructure produit. Vous allez voir comment choisir ce qui mérite d’être partagé, fermer une API, prévoir les exceptions et mesurer le coût de changement sans transformer la bibliothèque en framework interne incontrôlable.
Reconnaître une abstraction qui commence à figer le produit
Observer les contournements avant les tickets
Les signaux faibles sont des propriétés booléennes incompatibles, du CSS ciblant les classes internes, des slots utilisés pour remplacer tout le composant et des copies locales « temporaires ». Une documentation qui liste les options sans expliquer l’intention annonce souvent une abstraction devenue générique par accumulation.
Un autre signal apparaît quand une équipe attend une release du design system pour tester une hypothèse métier simple. La standardisation a déplacé le goulot. À l’inverse, si chaque équipe corrige séparément focus, clavier et responsive, le partage est insuffisant. La revue compare délai, défauts et nombre de forks.
Rejouez les évolutions récentes. Quel besoin a nécessité une nouvelle variante ? Était-il présent dans plusieurs produits ? Avait-il le même sens ? Si deux écrans se ressemblent mais n’ont pas les mêmes états ou actions, leur fusion visuelle peut être trompeuse.
Séparer primitive, composant, pattern et feature
Partager à la bonne profondeur
Une primitive encapsule un comportement stable : bouton, lien, champ, dialogue, onglets. Elle possède sémantique, clavier, focus, états et tokens. Un composant combine ces primitives pour une intention comme un sélecteur de date ou une carte de résultat. Un pattern décrit une composition récurrente, par exemple une page liste-filtre-détail.
La feature appartient au produit : gérer une commande, choisir une offre, déposer une pièce. Elle consomme les composants mais possède données, droits, règles et effets. La placer dans le design system crée une dépendance entre tous les produits et un domaine particulier. La dupliquer entièrement perd les garanties communes.
Le partage suit la stabilité. Une primitive accessible peut être stabilisée tôt. Un pattern émergent mérite deux ou trois usages réels avant abstraction. Une feature très distinctive reste locale, même si sa maquette ressemble à une autre. L’équipe peut extraire plus tard les invariants observés.
Cette séparation s’applique aussi aux responsabilités de support. Une anomalie de focus appartient à la primitive ; une action interdite, à la feature ; une composition qui déborde, au pattern ou à son contenu. Le diagnostic part de cette frontière et évite que l’équipe centrale absorbe chaque incident produit. Les corrections communes remontent dans le paquet, tandis que les règles locales restent dans leur domaine.
Fermer l’API publique du composant
Exprimer l’intention, pas la structure interne
Le contrat comprend propriétés, événements, slots, états, sémantique et garanties. Une propriété décrit une décision utile : taille, niveau de mise en avant, sélection. Elle n’expose pas chaque classe ou nœud. Les valeurs invalides échouent tôt en développement et reçoivent un repli sûr en production.
Les événements racontent ce qui s’est produit, sans exécuter eux-mêmes le métier. Un composant émet « sélection demandée » ; la feature décide si elle est autorisée et met à jour l’état. Le composant contrôlé reçoit valeur et callback. Le composant autonome ne garde que l’état purement local.
La documentation montre cas nominal, limites, contenu long, erreur, chargement, désactivation et absence. Elle indique aussi ce que le composant ne fait pas. Une API avec moins d’options et une composition claire évolue mieux qu’un objet de configuration capable de décrire toute page.
Borner variantes, slots et échappatoires
Préférer des axes orthogonaux
Une variante correspond à une différence stable et nommable. La densité peut être compacte ou confortable ; l’importance, neutre ou accentuée. Une variante « marketplace-blue-with-menu » mélange contexte, couleur et action. Les axes orthogonaux évitent l’explosion combinatoire, mais chaque combinaison supportée doit rester testée.
Les slots accueillent un contenu dans une zone prévue. Ils ne donnent pas accès aux détails internes. Une échappatoire peut exister pour un besoin rare : classe sur la racine, composant enfant ou composition externe. Elle est documentée, mesurée et ne permet pas de contourner sécurité ou sémantique.
Contre-intuitivement, refuser une variante peut accélérer le produit. L’équipe découvre que le besoin appartient à une feature locale, construit une composition claire et évite d’imposer son exception à tous les consommateurs. Le refus doit proposer une alternative, pas devenir une police du design.
Posséder comportement, sémantique et accessibilité
Commencer par l’élément natif
Un bouton utilise un bouton, un lien navigue, un champ possède libellé et relation d’erreur. Les composants personnalisés ajoutent seulement ce que le HTML ne fournit pas. La spécification HTML sur les custom elements décrit leur cycle technique, mais leur nom personnalisé ne leur donne aucune sémantique accessible automatique.
Le composant possède focus, clavier, annonce, état désactivé et erreurs. Les WCAG 2.2 servent de référence, complétées par des tests avec navigateurs et technologies d’assistance. Les équipes consommatrices ne doivent pas réinventer le clavier pour chaque instance.
Les contenus fournis par slot restent responsables de leur propre sémantique. Le contrat vérifie les préconditions possibles et documente les autres. Un dialogue ne peut pas garantir la qualité de tous les formulaires qu’il contient, mais il garantit titre, focus initial, fermeture et retour du focus.
Séparer composant visuel et données métier
Adapter la vue dans la feature
Le composant reçoit un modèle de présentation minimal. La feature transforme commande, produit ou client en titre, méta, actions et états. Le design system ne dépend pas du schéma de l’ERP. Un changement métier modifie l’adaptateur de vue, pas la primitive.
Les droits sont décidés côté backend puis exposés comme capacités autorisées. Masquer un bouton ne suffit pas. Le composant ne calcule pas « administrateur » depuis un rôle libre. L’action repasse par le cas d’usage qui répète l’autorisation.
Chargement, vide, erreur et données partielles sont des états explicites. Un squelette ne doit pas cacher indéfiniment une erreur. La feature choisit le message et la reprise ; le composant garantit la mise en page et l’annonce.
Versionner sans casser les produits consommateurs
Rendre les changements visibles
Le package suit une version et un changelog orienté impact. Un ajout compatible précède le retrait. Une dépréciation déclenche avertissement, guide et date. Les codemods automatisent les changements mécaniques, mais une évolution sémantique demande une revue produit.
Les tests visuels protègent la mise en page ; les tests unitaires, les états ; les tests d’accessibilité automatisés, une partie des règles. Des tests manuels couvrent clavier et lecteur d’écran. La matrice des consommateurs montre versions utilisées et composants critiques.
Une release candidate circule d’abord sur un produit pilote. Les autres consommateurs peuvent l’essayer sans modifier leur version stable. Cette fenêtre révèle les dépendances implicites et donne au changelog un retour concret. Une correction urgente reste rétroportable lorsque le coût et le risque le justifient, sans imposer l’ensemble de la prochaine évolution.
Le CSS respecte une surface publique. Les tokens peuvent évoluer avec alias et période de transition. Les consommateurs n’accèdent pas aux sélecteurs internes. Lorsqu’une correction de sécurité ou d’accessibilité doit être diffusée, l’équipe connaît les produits bloqués et le chemin de mise à jour.
Cas concret : tableau de dossiers pour trois produits
Cas concret. Trois portails affichent des dossiers sous forme de tableau. Le premier permet une sélection massive, le deuxième une validation ligne à ligne et le troisième un suivi en lecture seule. Une équipe propose un composant DataTable unique avec permissions, appels API et vingt colonnes configurables.
La cible partage primitives de tableau, tri, pagination, sélection et états accessibles. Chaque produit conserve sa feature et son adaptateur de colonnes. Un pattern documente la composition filtre-tableau-panneau. Les actions métier restent locales et passent par leurs API.
Par exemple, si le pilote couvre trois produits, huit états et deux tailles d’écran, alors les seuils restent locaux : aucune action interdite exposée, aucun clavier bloqué et aucune mise à jour imposant une migration simultanée. Une combinaison de variantes non testée n’entre pas dans l’API publique.
Le go est suspendu si une équipe surcharge les classes internes, si une feature dépend d’un type métier du design system ou si un changement de token casse un produit sans détection. Ces critères commandent correction ou maintien local ; ils ne promettent pas un composant universel.
Implémenter design system, paquets et documentation vivante
Fermer responsabilités et pipeline
Le dépôt sépare tokens, primitives, composants et exemples. Chaque paquet déclare entrées, sorties, dépendances et environnement supporté. La CI construit, teste et publie une version immuable. La journalisation du registry conserve auteur et provenance ; le monitoring des applications révèle erreurs et versions réellement chargées.
Les stories exécutables montrent états, thèmes, langues et tailles. Les tests couvrent composition, événements et contrats. Un seuil local bloque la publication si une régression critique d’accessibilité ou une rupture de type apparaît. Le rollback repointe une application vers une version connue sans réécrire les données.
Organiser la contribution
Une demande décrit problème, consommateurs, cas existants, alternatives et owner. Un prototype local valide l’intention. La revue design et technique décide extraction, composition ou maintien local. Le comité ne juge pas uniquement la conformité visuelle : il évalue coût complet, accessibilité et évolution.
Le runbook explique publication, dépréciation, retrait et incident. Les dépendances tierces ont une version et une condition de sortie. Un composant ne dépend pas d’un service réseau caché. La feature injecte les données et possède son retry.
Mesurer adoption, cohérence et coût de changement
Compter les usages utiles, pas seulement les composants
Suivez produits consommateurs, versions, forks, surcharges, défauts et délai de mise à jour. Un taux d’adoption élevé avec de nombreux contournements n’est pas une réussite. Une petite primitive utilisée partout peut apporter plus qu’un composant riche adopté une fois.
Le coût d’évolution se mesure entre décision et mise à jour effective, y compris tests et corrections. La charge support interne, les régressions et les releases coordonnées révèlent la rigidité. Les équipes expliquent pourquoi elles restent sur une ancienne version.
La revue retire variantes inutilisées et fusionne les doublons seulement après observation. Elle publie aussi les exceptions acceptées. La cohérence n’exige pas l’identité : une différence possédée peut rester locale si elle protège un besoin réel.
Pour qui cette stratégie de composants est utile
Réunir design, frontend, produit et accessibilité
Elle concerne organisations avec plusieurs produits, équipes ou parcours durables. Designers, frontend, produit, accessibilité, QA et run participent. Le design system a un roadmap et un budget, pas seulement une documentation.
Un produit en exploration peut commencer avec des composants locaux et quelques primitives. Extraire trop tôt ralentit l’apprentissage. Dès que plusieurs équipes corrigent les mêmes comportements ou qu’une cohérence contractuelle est requise, le partage devient rentable.
Le nombre d’applications ne suffit pas. Un seul produit complexe peut bénéficier de contrats stables ; dix sites marketing simples peuvent partager un thème plus léger. La décision suit invariants, cadence et coût d’incohérence.
Éviter les erreurs fréquentes
Créer le composant universel
Les propriétés s’accumulent et les combinaisons deviennent impossibles à tester. Séparez primitives, patterns et features. Composez les besoins rares hors de l’API commune.
Exposer le DOM comme contrat
Les consommateurs ciblent les classes et bloquent toute refonte. Publiez propriétés, événements et slots bornés. Traitez les sélecteurs internes comme privés.
Centraliser les décisions métier
Le design system devient dépendant d’un domaine. Gardez données, droits et effets dans la feature ; partagez l’interaction et la présentation stable.
Mesurer la conformité visuelle uniquement
Une capture identique peut masquer clavier cassé et API rigide. Mesurez accessibilité, adoption réelle, forks et délai de changement.
Arbitrage : standardiser, composer ou laisser local
Bloc de décision. Standardisez un invariant utilisé et testable. Composez lorsque plusieurs primitives résolvent le besoin. Laissez local une feature distinctive ou encore instable. Extrayez plus tard les comportements observés plutôt que les ressemblances de maquette.
Priorisez HTML natif, accessibilité, états et API avant les thèmes. Différez une variante sans second usage. Refusez une propriété qui expose le métier. Conservez une échappatoire bornée et mesurée pour éviter les forks clandestins.
- Nommer le niveau de partage.
- Tester chaque état et combinaison supportée.
- Documenter limites et chemin de dépréciation.
- Décider l’extraction après des usages réels.
Plan d’action sur huit semaines
Semaines 1 et 2 : inventorier les usages
Choisissez trente écrans, dix incidents et cinq évolutions. Relevez primitives, copies, variantes, surcharges et features. Mesurez délai, forks et défauts d’accessibilité. Classez ce qui est stable, émergent ou métier. Le premier livrable est une carte des responsabilités.
Pour chaque candidat partagé, réunissez son markup, ses états, ses consommateurs et les changements des six derniers mois. Une ressemblance de capture ne suffit pas. Si deux produits utilisent le même bouton mais divergent sur l’action ou le droit, alors partagez la primitive et conservez l’orchestration dans chaque feature.
Semaines 3 à 5 : fermer trois composants
Choisissez une primitive, un composant et un pattern. Écrivez API, états, sémantique, limites et ownership. Construisez stories, tests, version et changelog. Migrez deux usages sans adapter le composant à chaque détail.
Provoquez contenu long, langue, erreur, clavier, zoom, thème et API inconnue. Vérifiez entrées, sorties, dépendances, journalisation et rollback de paquet. Une équipe externe à la création exécute la migration depuis la documentation.
Ajoutez un test de coexistence entre la version stable et la candidate. Le produit pilote doit pouvoir revenir au paquet précédent sans modifier ses données. Mesurez le temps nécessaire pour comprendre un changement, adapter un usage et diagnostiquer une régression ; si cette chaîne dépend de l’auteur initial, alors la documentation et le contrat restent insuffisants.
Semaines 6 à 8 : ouvrir et gouverner
Publiez une version stable pour trois produits. Suivez adoption, forks, régressions et demandes de variantes. Jouez dépréciation et retour à la version précédente. Étendez lorsque les équipes contribuent sans dépendre d’une connaissance orale.
La revue ferme d’abord sémantique et accessibilité ; ensuite les contrats ; puis la cohérence visuelle fine. Une feature instable reste locale. Toute nouvelle variante indique usages, tests, owner et condition de retrait.
La revue finale examine aussi les demandes refusées. Elle vérifie que la solution locale utilise encore les primitives communes et qu’aucun fork clandestin n’a été créé. Une exception répétée dans deux produits devient un nouveau candidat, mais elle repasse par l’inventaire et les scénarios hostiles avant d’entrer dans l’API publique.
- Inventorier usages et contournements.
- Choisir le bon niveau de partage.
- Éprouver API, accessibilité et migration.
- Étendre avec versionnement et gouvernance.
Approfondir rendu, recherche et formulaires
Le guide des stratégies de rendu aide à décider activation et hydratation. Le guide search et navigation applique ces contrats aux facettes.
Le guide des formulaires complexes approfondit états, erreurs et reprise. Ces lectures doivent nourrir des composants observés, pas un catalogue théorique.
- Partager comportements stables avant les features.
- Conserver les données métier hors de la bibliothèque.
- Jouer une dépréciation avant de multiplier les consommateurs.
Conclusion : stabiliser les invariants, laisser évoluer le métier
Un composant sur mesure ne fige pas le produit par nature. Il le fige lorsqu’il expose trop de structure, mélange données et interaction ou transforme chaque exception en variante commune.
Les primitives possèdent sémantique et accessibilité. Les composants portent une intention. Les patterns organisent un parcours. Les features conservent droits, données et effets. Cette séparation donne une surface stable sans nier les différences entre produits.
Le meilleur indicateur est le coût d’une évolution réelle : l’équipe peut-elle la livrer, la tester et la diffuser sans fork ni migration générale ? Si chaque changement exige de connaître les classes internes, le contrat est trop faible.
Dawap peut vous accompagner pour structurer cette bibliothèque dans une démarche de développement web sur mesure : audit des usages, architecture de composants, accessibilité, API, tests, versionnement, migration et gouvernance du design system.