Les trois niveaux et leur utilité réelle
La convention est quasi universelle, ce qui rend facile l'adoption de la structure sans en comprendre la logique. Chaque niveau répond à une question différente, et savoir laquelle permet d'éviter de placer les éléments au mauvais endroit.
| Réponses | Exemple | Utilisé par | |
|---|---|---|---|
| Primitive | Quelles valeurs existent dans ce design ? | blue-600, space-4, radius-md | Le niveau sémantique uniquement. Jamais le code produit |
| Sémantique | À quoi sert cette valeur ? | --color-danger, --text-muted, --surface-raised | Code produit. C'est la couche sur laquelle les développeurs s'appuient |
| Composant | Où un composant diffère-t-il légitimement ? | --button-primary-bg, --tooltip-surface | Ce composant uniquement, et rarement |
La règle qui rend ce système efficace, et celle qui est la plus souvent transgressée : rien en dehors du niveau sémantique ne peut référencer une primitive. Dès qu'un composant utilise blue-600 directement, le niveau primitive devient une API publique et vous ne pouvez plus modifier une valeur sans auditer l'ensemble du code — ce qui était précisément la raison d'être des niveaux.
:root {
/* Tier 1: primitives. Values only. Nobody uses these directly. */
--blue-600: #2563eb;
--red-600: #dc2626;
--gray-500: #6b7280;
/* Tier 2: semantic. Roles. This is the public API. */
--color-primary: var(--blue-600);
--color-danger: var(--red-600);
--text-muted: var(--gray-500);
/* Tier 3: component. Only where a component truly deviates. */
--button-danger-bg: var(--color-danger);
}
/* ✅ product code */
.alert { color: var(--color-danger); }
/* ❌ reaches past the semantic layer */
.alert { color: var(--red-600); }Le modèle de nommage
Lecture de gauche à droite, du général au spécifique : catégorie, rôle, variante, état. Tous les tokens n'ont pas besoin de ces quatre éléments, et ceux qui en ont sont généralement interactifs.
| Catégorie | Rôle | Variante | État | |
|---|---|---|---|---|
color-text-primary | color | text | primary | — |
color-surface-raised | color | surface | raised | — |
color-action-primary-hover | color | action | primary | hover |
space-inset-lg | space | inset | lg | — |
border-subtle | border | — | subtle | — |
La cohérence importe bien plus que le modèle choisi. Une base de code où la moitié des tokens s'appellent text-color-muted et l'autre moitié color-text-muted oblige tout le monde à vérifier la syntaxe à chaque fois, indéfiniment. Choisissez un ordre, documentez-le et imposez-le lors des revues.
Un avantage pratique de l'ordre allant du général au spécifique : vos tokens se trient alphabétiquement en groupes cohérents. Tous les tokens color-surface-* sont regroupés dans l'autocomplétion de l'éditeur, transformant ainsi la convention de nommage en mécanisme de découverte.
Voici le modèle appliqué plutôt que décrit. Lisez les noms de rôles, pas les couleurs — la question à laquelle chacun doit répondre est « à quoi cela sert-il ? ». Un nom qui répond uniquement à « de quelle couleur est-ce ? » a échoué par rapport au niveau auquel il se situe.
Le test pour détecter un mauvais nom
Une seule question permet de résoudre la plupart des débats sur le nommage en quelques secondes :
Si le design changeait, ce nom serait-il toujours exact ?
Appliquez ce test à des cas réels et les réponses sont sans ambiguïté :
| Survit ? | Pourquoi | |
|---|---|---|
--color-brand-blue | Non | Passez au vert et le nom devient un mensonge que personne n'ose corriger |
--color-primary | Oui | Le rôle ne change pas lorsque la teinte change |
--text-small-gray | Non | Deux faits d'apparence, dont les deux sont susceptibles d'évoluer |
--text-muted | Oui | Nomme l'intention : un texte désaccentué |
--shadow-card | Non | Encode le mécanisme. Passez à une élévation par trait fin et le nom devient erroné |
--elevation-raised | Oui | Nomme l'effet. Il peut s'agir d'une ombre, d'une bordure ou d'un niveau de surface |
Le cas de --shadow-card est subtil et mérite qu'on s'y attarde. Nommer un token d'après son implémentation fige cette implémentation. Une fois que chaque carte dans la base de code utilise box-shadow: var(--shadow-card), passer à une élévation basée sur des bordures devient un refactoring plutôt qu'un simple changement de token — ce qui est précisément le couplage que les tokens étaient censés supprimer.
C'est avec le mode sombre que les noms basés sur l'apparence meurent publiquement. --gray-100 comme « fond clair » est correct dans un thème et inversé dans l'autre ; on se retrouve donc avec un --gray-100 contenant une valeur presque noire, et chaque développeur est confus. --surface-base reste vrai dans les deux cas.
Pourquoi le niveau composant ne cesse de croître
La plupart des systèmes de tokens qui échouent le font ici. Le niveau composant commence petit et légitime, puis absorbe tout, jusqu'à ce que vous vous retrouviez avec quatre cents tokens, dont la moitié n'a qu'un seul utilisateur.
Le mécanisme est toujours le même. Quelqu'un a besoin d'un fond de bouton qui n'est pas tout à fait --color-primary. Ajouter --button-primary-bg prend trente secondes, alors que l'ajouter au niveau sémantique nécessite une discussion. Le token de composant est donc créé, la personne suivante fait de même, et le niveau sémantique cesse d'être la source de vérité sans que personne ne l'ait décidé.
| Le vrai problème | |
|---|---|
| Plusieurs composants ont besoin de la même valeur hors-sémantique | Un token sémantique manquant. Nommez le rôle et faites-le monter en gamme |
| Un composant a besoin d'une valeur réellement unique | Légitime. C'est l'objet même de ce niveau. Cela doit rester rare |
| Toute une surface nécessite des valeurs différentes | Il manque un thème ou un scope, et non des tokens de composants. Regardez ce que Encore a fait avec les layers |
| Personne ne sait quel token sémantique utiliser | Le niveau sémantique est sous-spécifié ou mal nommé |
Un audit utile : comptez les tokens de niveau composant qui n'ont qu'un seul utilisateur. Si ce nombre est élevé, le niveau est utilisé comme une solution de secours, et la correction doit se faire en amont.
Cinq erreurs et leur coût respectif
Celles-ci reviennent dans presque tous les systèmes de tokens qui finissent par être abandonnés. Chacune a une correction simple si elle est détectée tôt, et coûteuse dans le cas contraire.
- 1
Échelles numérotées sans ancrage
De
color-1àcolor-12ne signifie rien pour personne, et les chiffres n'acquièrent un sens que par folklore. Les échelles numérotées sont acceptables dans le niveau primitif, où le chiffre suit une dimension réelle comme la luminosité. Elles ne sont jamais acceptables dans le niveau sémantique, car tout l'intérêt de ce niveau est d'indiquer à quoi sert l'élément. - 2
Encoder le thème dans le nom
Utiliser
--light-bget--dark-bgcomme tokens distincts signifie que chaque composant doit référencer les deux et créer une condition. Un nom, deux valeurs, basculées par le thème : c'est à cela que sert la couche de tokens. Si vous trouvezif (theme === 'dark')dans le code d'un composant, c'est que les tokens sont mal nommés./* ❌ */ --light-bg: #fff; --dark-bg: #0a0a0a; /* ✅ */ --surface-base: #fff; [data-theme="dark"] { --surface-base: #0a0a0a; } - 3
Des tailles nommées selon leur usage actuel
--text-heroconvient parfaitement jusqu'à ce que la taille « hero » apparaisse dans un tableau de prix.--text-4xlou--font-scale-7nomment l'étape, pas le site, et survivent à la réutilisation. Nommez par position dans une échelle, pas selon le premier client. - 4
Des couleurs de statut servant également de couleurs de marque
C'est la manière la plus courante pour un système de devenir incapable d'afficher un état. Si le vert de la marque et le vert de succès utilisent le même token, vous ne pouvez pas modifier le style de la marque sans changer l'apparence du succès, et vous ne pouvez pas distinguer une ligne saine d'une ligne brandée. Gardez l'ensemble des statuts réservé et précisez-le dans un commentaire.
- 5
Des abréviations que seule une personne sait interpréter
--clr-bg-scndryéconomise onze caractères mais impose à chaque lecteur une étape de décodage permanente, y compris pour un modèle qui doit deviner siscndrysignifie « secondary » ou s'il s'agit d'une faute de frappe. L'autocomplétion rend la longueur quasi gratuite. Écrivez les mots en entier.
Le second point mérite un audit immédiat. Utilisez grep sur vos composants pour trouver les conditionnels de thème : chacun d'eux est un token qui aurait dû être un nom unique avec deux valeurs, et chaque occurrence est un endroit où le mode sombre divergera silencieusement du mode clair.
Des noms qui survivent à la sortie de votre base de code
Les tokens doivent être de plus en plus mobiles : d'un outil de design vers le CSS, dans un thème Tailwind, dans une plateforme native, dans un élément de registre shadcn, ou dans un DESIGN.md lu par un agent. Cela impose une contrainte sur les noms que la plupart des équipes ignorent jusqu'à ce que le premier export échoue.
| Portable ? | Pourquoi | |
|---|---|---|
| Points ou slashs comme séparateurs | Risqué | color.text.muted est naturel en JSON mais illégal dans une propriété personnalisée CSS. Les traits d'union survivent partout. |
| Majuscules ou casse mixte | Risqué | Certaines cibles normalisent la casse, d'autres non. L'utilisation exclusive de minuscules élimine la question. |
| Imbrication profonde | Risqué | color.semantic.text.emphasis.high devient illisible une fois aplati et personne ne le tapera deux fois. |
| Plat, minuscules, avec traits d'union | Oui | --color-text-muted fonctionne comme variable CSS, clé JSON, clé Tailwind et mot simple dans une phrase. |
La règle pratique : choisissez des noms qui soient simultanément une propriété personnalisée CSS valide, une clé JSON valide et une phrase anglaise lisible. Le format plat, en minuscules et avec traits d'union satisfait ces trois critères, et les groupes imbriqués du format de token DTCG/W3C peuvent être générés à partir d'un ensemble plat bien plus facilement que l'inverse.
Un autre test de portabilité utile : pouvez-vous prononcer le nom du token à voix haute en réunion sans avoir à l'épeler ? Si deux personnes ne s'entendent pas sur la prononciation d'un token, elles ne l'utiliseront pas non plus de manière cohérente à l'écrit.
Harmoniser les noms entre le design et le code
La décision de nommage ayant le plus d'impact n'est pas le pattern. C'est de savoir si les noms dans votre outil de design sont identiques aux noms dans le code.
Le SLDS 2 de Salesforce est l'exemple publié le plus clair : sa bibliothèque Figma utilise les mêmes noms de hooks sémantiques que le CSS — leurs propres exemples sont radius-border-4 et font-scale-4 — ainsi, les designs correspondent un pour un au code réel. Leur objectif affiché est un vocabulaire partagé faisant le pont entre le design et le développement.
L'effet pratique est la disparition complète d'une catégorie de bugs de handoff. Lorsqu'un designer dit font-scale-4 et qu'un développeur tape font-scale-4, il n'y a pas d'étape de traduction et donc aucun risque de perte de sens. Comparez cela à un style Figma nommé « Heading / Large » correspondant à une variable CSS nommée --text-2xl, où chaque handoff est une recherche et chaque recherche est une occasion de se tromper.
Si vous ne pouvez effectuer qu'un seul changement dans votre système de tokens, faites correspondre les noms entre les outils. Cela coûte un renommage et supprime une taxe permanente.
Nommer lorsque l'utilisateur est un agent
Le nommage des tokens était autrefois une question d'ergonomie humaine : autocomplétion, lisibilité, onboarding. Désormais, le lecteur le plus assidu de votre fichier de tokens est un agent de code, et cela change la nature des erreurs critiques.
Un humain qui ne sait pas lequel de deux gris utiliser posera la question, ou en choisira un et sera corrigé lors de la revue. Un modèle en choisira un, silencieusement, dans chaque fichier qu'il touchera, et l'incohérence s'installera plus vite que la revue ne pourra la détecter. L'ambiguïté dans le niveau sémantique est un défaut bien plus coûteux qu'auparavant.
Nous avons analysé 299 fichiers DESIGN.md publiés pour être lus par des agents et avons constaté que 86 % spécifient les couleurs par des valeurs hexadécimales brutes sans aucun rôle sémantique associé. Pas des tokens mal nommés — aucun token. Un modèle à qui l'on donne #6b7280 en lui disant qu'il fait partie de la palette l'utilisera partout où un gris moyen semble plausible : texte du corps, bordures, icônes, placeholders, états désactivés. Cinq fonctions différentes, une seule valeur, et aucun moyen de les modifier indépendamment plus tard.
| Ce que fait l'agent | |
|---|---|
Gray: #6b7280 | L'utilise pour le texte du corps, les bordures, les icônes, les placeholders et les états désactivés sans distinction |
--text-muted: #6b7280 — texte secondaire et de soutien uniquement. Les bordures utilisent --border-subtle. L'état désactivé utilise --text-disabled. | L'utilise pour le texte de support. Les autres fonctions ont leurs propres noms, elles peuvent donc diverger plus tard |
La seconde version coûte trois lignes supplémentaires mais permet d'assombrir vos bordures sans assombrir vos légendes — un changement dont vous aurez besoin, et que la première version rend impossible sans un audit complet de la base de code.
Les kits Identity Forge proposent 28 rôles de couleurs sémantiques pour les modes clair et sombre, ainsi que la typographie, l'espacement et l'élévation, sérialisés dans un fichier DESIGN.md qu'un agent lit avant toute écriture. Parcourez les kits ou consultez l'article explication des design tokens de couleur sémantique.
Un ensemble de départ
Si vous nommez un système de zéro, c'est un minimum justifiable. Il est volontairement restreint — un système que personne ne peut mémoriser finit par être ignoré.
/* Surfaces — what things sit on */
--surface-base /* the page */
--surface-raised /* cards, panels */
--surface-overlay /* modals, popovers */
--surface-sunken /* wells, inset areas */
/* Text — by emphasis, never by colour */
--text-primary
--text-secondary
--text-muted
--text-disabled
--text-on-accent /* text sitting on the accent colour */
/* Borders — by weight of presence */
--border-subtle
--border-strong
--border-focus
/* Action — the interactive colour and its states */
--action-primary
--action-primary-hover
--action-primary-active
/* Status — reserved. Nothing decorative uses these. */
--status-success
--status-warning
--status-danger
--status-infoDeux remarques sur cet ensemble. Les tokens de texte sont nommés selon l'emphase plutôt que la couleur, afin de rester cohérents en mode sombre. Les tokens de statut comportent un commentaire les réservant, car la cause la plus fréquente de rupture d'un système de statut est l'utilisation du vert « succès » comme accent décoratif, rendant alors impossible la distinction entre une ligne valide et une ligne aux couleurs de la marque.
Quelle est la meilleure convention de nommage pour les design tokens ?
Trois niveaux — primitive, sémantique, composant — avec des noms lus du général au spécifique : catégorie, rôle, variante, état. L'ordre spécifique importe bien moins que l'application systématique d'une convention, car le coût réel de l'incohérence est une recherche fastidieuse à chaque utilisation.
Quelle est la différence entre les tokens primitives et sémantiques ?
Une primitive nomme une valeur (blue-600) et ne précise pas où elle s'applique. Un token sémantique nomme une fonction (--color-primary) et pointe vers une primitive. Le code produit ne devrait utiliser que des tokens sémantiques, afin que le changement d'une valeur soit une modification d'une seule ligne plutôt qu'un audit de la base de code.
Dois-je nommer les tokens d'après les couleurs ?
Uniquement au niveau primitive, où nommer la valeur est l'objectif. Au niveau sémantique, jamais : --color-brand-blue devient un mensonge dès l'instant où vous changez d'identité visuelle, et personne ne le renomme car trop d'éléments en dépendent. Nommez le rôle et laissez la valeur évoluer en dessous.
Combien de design tokens un système doit-il avoir ?
Moins que vous ne le pensez. Une couche sémantique d'environ 25 à 40 rôles de couleurs, plus les échelles de typographie, d'espacement et d'élévation, couvre la plupart des produits. Si le nombre dépasse la centaine, vérifiez combien de tokens n'ont qu'un seul utilisateur — ce chiffre vous dira si vous avez un système ou une simple liste.
Le nommage des tokens est-il plus important maintenant que l'IA écrit le code ?
Oui, car le mode de défaillance a changé. Un humain incertain du gris à utiliser pose la question ou est corrigé lors de la revue. Un modèle en choisit un silencieusement dans chaque fichier qu'il touche, donc l'ambiguïté se propage plus vite que la revue ne peut la détecter. La solution réside dans des noms de rôles sans ambiguïté avec des objectifs définis.