Files
design-system/PROTOCOLE.md

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-width uniquement (jamais max-width pour 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 dans reset.css ; tout JS d'animation doit aussi tester matchMedia("(prefers-reduced-motion: reduce)") (cf. js/reveal.js).
  • Budget reveal : fade + translate court (≤ 12px), durées --dur-base/--dur-slow max, 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 le on-* correspondant comme couleur de texte sur ces fonds.
  • Layers : tokens.css vit dans @layer tf-tokens, reset.css dans @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 !important layeré, 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)

  1. cp theme/base.css theme/mon-site.css
  2. 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.
  3. Ne toucher à rien d'autre : pas d'échelles, pas de spacing, pas de motion dans un thème.
  4. Vérifier les contrastes AA (4.5:1 texte courant, 3:1 grands titres/UI) dans les deux modes — y compris --on-primary sur --primary et --on-accent sur --accent.
  5. Charger les @font-face côté site (self-host / fontsource) ; le thème ne définit que les stacks.
  6. 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-visible global dans reset.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).
  • lang défini sur <html> (prop de BaseLayout), aria-current="page" sur le lien actif, alt sur 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.