Adoption
Conformité
Ces règles sont vérifiables : un relecteur (ou un agent) peut les cocher une par une sur une diff. Elles ne sont pas des préférences de style — ce sont les conditions mécaniques de la parité. Une PR qui les respecte reste dans la ligne ; une PR qui les enfreint la casse.
| Règle | Ce qu'on vérifie |
|---|---|
| API label là où un nom accessible est requis | Aucun IconButton, aucun contrôle icône sans label. Le glyphe texte ×/✕ est banni : icône Lucide + label « Fermer ». |
| Pas de #hex en dur — tokens uniquement | Aucun #hex ni rgb() en dur dans le TSX/CSS d'app. Exceptions légitimes : email/PDF, logos tiers, data-viz où la couleur porte une donnée. |
| 15px interdit — échelle typo respectée | Aucun 15px (→ var(--fs-body)). Aucune valeur hors échelle (17/19/22 en dur → token le plus proche). |
| Pas de border-left décorative bricolée | Aucune border-left 3px décorative sur bloc coloré. La blockquote typographique reste légitime. |
| Un composant = @forme-ch/ui, jamais dupliqué | Aucun composant d'UI réécrit dans l'app, aucun style inline qui contourne le socle (padding pour bricoler un carré, popover fait main). |
| Radius via tokens | Aucun rayon en px en dur. Seule exception : 50% / 9999px pour cercles purs (avatars, points de statut, switch). |
La checklist
☐ API label là où un nom accessible est requis
Conforme : Tout contrôle sans texte visible (icône seule, bouton de fermeture) porte un label.
On vérifie : Aucun IconButton, aucun contrôle icône sans label. Le glyphe texte ×/✕ est banni : icône Lucide + label « Fermer ».
Conforme : Tout contrôle sans texte visible (icône seule, bouton de fermeture) porte un label.
On vérifie : Aucun IconButton, aucun contrôle icône sans label. Le glyphe texte ×/✕ est banni : icône Lucide + label « Fermer ».
☐ Pas de #hex en dur — tokens uniquement
Conforme : Couleurs référencées via var(--color-*). Le thème sombre suit automatiquement.
On vérifie : Aucun #hex ni rgb() en dur dans le TSX/CSS d'app. Exceptions légitimes : email/PDF, logos tiers, data-viz où la couleur porte une donnée.
Conforme : Couleurs référencées via var(--color-*). Le thème sombre suit automatiquement.
On vérifie : Aucun #hex ni rgb() en dur dans le TSX/CSS d'app. Exceptions légitimes : email/PDF, logos tiers, data-viz où la couleur porte une donnée.
☐ 15px interdit — échelle typo respectée
Conforme : Tailles prises dans l'échelle : 10/11/12/13/14/16/18/20/28/48, via les tokens --fs-*.
On vérifie : Aucun 15px (→ var(--fs-body)). Aucune valeur hors échelle (17/19/22 en dur → token le plus proche).
Conforme : Tailles prises dans l'échelle : 10/11/12/13/14/16/18/20/28/48, via les tokens --fs-*.
On vérifie : Aucun 15px (→ var(--fs-body)). Aucune valeur hors échelle (17/19/22 en dur → token le plus proche).
☐ Pas de border-left décorative bricolée
Conforme : Un bloc teinté = fond color-mix + filet 1px complet (langage Badge). Le statut est porté par l'icône colorée.
On vérifie : Aucune border-left 3px décorative sur bloc coloré. La blockquote typographique reste légitime.
Conforme : Un bloc teinté = fond color-mix + filet 1px complet (langage Badge). Le statut est porté par l'icône colorée.
On vérifie : Aucune border-left 3px décorative sur bloc coloré. La blockquote typographique reste légitime.
☐ Un composant = @forme-ch/ui, jamais dupliqué
Conforme : Le composant vient du paquet. Une lacune se corrige dans le paquet, pas dans l'app.
On vérifie : Aucun composant d'UI réécrit dans l'app, aucun style inline qui contourne le socle (padding pour bricoler un carré, popover fait main).
Conforme : Le composant vient du paquet. Une lacune se corrige dans le paquet, pas dans l'app.
On vérifie : Aucun composant d'UI réécrit dans l'app, aucun style inline qui contourne le socle (padding pour bricoler un carré, popover fait main).
☐ Radius via tokens
Conforme : Rayons pris dans --radius-inner / --radius-element / --radius-container.
On vérifie : Aucun rayon en px en dur. Seule exception : 50% / 9999px pour cercles purs (avatars, points de statut, switch).
Conforme : Rayons pris dans --radius-inner / --radius-element / --radius-container.
On vérifie : Aucun rayon en px en dur. Seule exception : 50% / 9999px pour cercles purs (avatars, points de statut, switch).
Exemples avant / après
Réflexe avant de styler. Grep un sélecteur avant de le créer : il peut déjà
exister, divergent (piège classique des refontes successives). Et rappelle-toi : la bonne réponse
à une lacune du socle n'est jamais du CSS d'app — c'est un enrichissement du paquet.