6.4 KiB
6.4 KiB
PROTOCOLE — design system trans-former.fr
La « matrice » : les règles que tout site de la constellation applique. Un build n'est pas fini tant que la Definition-of-Done en bas n'est pas cochée.
1. Mobile-first — règle de base
- Les styles de base ciblent 360px. On monte ensuite avec des media queries
min-widthuniquement (jamaismax-widthpour la structure ; une exception encadrée : l'état hamburger de la Nav). - Typographie fluide en
clamp()— l'échelle--fs-*est calibrée entre 360px et 1280px, ne pas la redéfinir par breakpoint. - Cibles tactiles ≥ 44px (boutons, liens de nav, toggles). Sur
pointer: coarse, aucune taille ne descend en dessous.
Breakpoints — constantes
Les variables CSS ne fonctionnent pas dans @media : ces valeurs sont des constantes de la constellation, à utiliser telles quelles partout.
| Nom | px | rem | Usage type |
|---|---|---|---|
| base | 360 | — | styles par défaut (pas de media query) |
| sm | 480 | 30rem | ajustements petits écrans larges |
| md | 768 | 48rem | passage nav inline, grilles 2-3 col |
| lg | 1024 | 64rem | layouts larges |
| xl | 1280 | 80rem | plafond de l'échelle fluide |
Écrire les media queries en rem (@media (min-width: 48rem)).
2. Motion charter
- Motion piloté-utilisateur : toute animation répond à une action (scroll, hover, focus, clic). Jamais d'auto-play — pas de carrousel automatique, pas d'animation en boucle — sans pause au survol/focus et contrôles visibles.
@media (prefers-reduced-motion: reduce)coupe tout mouvement non essentiel. Le kill-switch global est dansreset.css; tout JS d'animation doit aussi testermatchMedia("(prefers-reduced-motion: reduce)")(cf.js/reveal.js).- Budget reveal : fade + translate court (≤ 12px), durées
--dur-base/--dur-slowmax, easing--ease-out. Pas de zoom, pas de rotation, pas de parallaxe décorative. - Le JS est progressif : sans JS, rien n'est masqué, rien n'est cassé (garde
html[data-js]).
3. Lois design (anti-patterns) — appliquées sans exception
- ❌
border-left/border-right> 1px colorée comme accent (card, callout) - ❌ gradient text (
background-clip: text) - ❌ glassmorphisme décoratif par défaut
- ❌ template hero-metric (grand chiffre + petit label + gradient accent)
- ❌ grilles de cards identiques icon+heading+text
- ❌ modal comme premier réflexe UX
- ❌ em-dashes (
—/--) dans les textes UI - ❌ Inter par défaut sans raison
- ❌ gradients violets sans justification
- ❌ dark glow décoratif
4. Tokens — conventions de nommage
- Nommage par rôle, jamais par couleur brute :
--primary, pas--green. Un thème peut changer toute la palette sans toucher un composant. - Préfixes d'échelle :
--fs-*(font-size),--lh-*(line-height),--fw-*(weight),--space-*,--radius-*,--shadow-*,--dur-*,--ease-*,--z-*. - Paires de contraste :
--primary/--on-primary,--accent/--on-accent. Toujours utiliser leon-*correspondant comme couleur de texte sur ces fonds. - Layers :
tokens.cssvit dans@layer tf-tokens,reset.cssdans@layer tf-reset. Les thèmes et le CSS des sites restent non-layerés → ils gagnent toujours sur la fondation, quel que soit l'ordre de chargement. Ne jamais mettre un thème dans un layer. (Exception voulue : le kill-switch reduced-motion du reset est en!importantlayeré, il bat donc tout le monde.) - Le schéma (noms + échelles) est universel et gelé : en ajouter demande une mise à jour ici + dans
tokens.css+ dans les thèmes. En retirer/renommer = breaking change pour tous les sites. - Tailwind 4 (site racine) : les tokens sont mappés via
tailwind.css(@theme inline). Les namespaces en collision de nom (--font-*,--radius-*,--shadow-*,--ease-*) s'utilisent en syntaxe var arbitraire :rounded-(--radius-md),shadow-(--shadow-md),ease-(--ease-out),font-(family-name:--font-heading).
5. Ajouter un thème (nouveau site)
cp theme/base.css theme/mon-site.css- Remplacer palette claire, palette sombre (bloc
[data-theme="dark"]et duplication@media (prefers-color-scheme: dark)avec le garde:not([data-theme="light"])), et les deux stacks de polices. - Ne toucher à rien d'autre : pas d'échelles, pas de spacing, pas de motion dans un thème.
- Vérifier les contrastes AA (4.5:1 texte courant, 3:1 grands titres/UI) dans les deux modes — y compris
--on-primarysur--primaryet--on-accentsur--accent. - Charger les
@font-facecôté site (self-host / fontsource) ; le thème ne définit que les stacks. - L'ajouter à la page démo (
src/pages/demo/mon-site.astro, 4 lignes) et valider le kitchen sink.
Clair/sombre : mode clair par défaut + sombre via préférence système, le toggle explicite (data-theme) gagne toujours dans les deux sens. Un site peut être sombre par défaut (cf. theme/aep.css : :root sombre, variante claire sur [data-theme="light"] seulement).
6. Accessibilité — socle
- Contraste AA partout, dans les deux modes.
- Focus visible partout :
:focus-visibleglobal dansreset.css, ne jamais le supprimer sans remplacement équivalent. - Navigation clavier complète : hamburger avec
aria-expanded/aria-controls, fermeture Échap, focus trap panneau ouvert, skip-link (BaseLayout). langdéfini sur<html>(prop deBaseLayout),aria-current="page"sur le lien actif,altsur toute image porteuse de sens.
7. Definition-of-Done — checklist de fin de build
Avant de déclarer un site « fini » :
- Testé à 360, 768, 1280 px — aucun débordement horizontal, hiérarchie lisible aux trois tailles.
- Testé en clair ET sombre (préférence système + toggle) — contrastes AA dans les deux.
- Testé avec prefers-reduced-motion: reduce — plus aucun mouvement non essentiel.
- Testé sans JS — contenu et navigation accessibles (liens visibles, rien de masqué).
- Navigation clavier seul : tout est atteignable, focus visible, hamburger Échap + trap OK.
- Cibles tactiles ≥ 44px sur mobile.
- Zéro valeur en dur qui duplique un token (couleur hex, taille de police, spacing) dans le CSS du site.
- Aucune violation des lois design (§3).
- Le site n'importe qu'un seul
theme/*.css; en changer suffit à changer le look. - Lighthouse a11y ≥ 95, aucune erreur console.