86 lines
6.4 KiB
Markdown
86 lines
6.4 KiB
Markdown
# 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.
|