diff --git a/HANDOFF.md b/HANDOFF.md new file mode 100644 index 0000000..cd077a9 --- /dev/null +++ b/HANDOFF.md @@ -0,0 +1,83 @@ +# HANDOFF — P1 fondation → P2 (TMIP) / P3 (racine) + +État au 2026-07-19. Repo : `git.trans-former.fr/jules/design-system`, branche `main`. Local : `~/dev/design-system` (Linux). + +## 1. Le contrat — ce que P2/P3 consomment + +### Tokens (schéma complet, `tokens.css`, layer `tf-tokens`) + +- **Couleur (rôles)** : `--bg` `--bg-alt` `--surface` `--surface-2` `--text` `--text-muted` `--text-subtle` `--border` `--border-strong` `--primary` `--primary-hover` `--on-primary` `--accent` `--on-accent` `--link` `--link-hover` `--focus-ring` `--success` `--warning` `--danger` +- **Typo** : `--font-heading` `--font-body` `--font-mono` · tailles fluides `--fs-xs|sm|base|lg|xl|2xl|3xl|4xl` (clamp 360→1280) · `--lh-tight|base|loose` · `--fw-regular|medium|semibold|bold` +- **Spacing** : `--space-2xs|xs|sm|md|lg|xl|2xl|3xl` (4/8px, fluide sur 2xl/3xl) +- **Rayons** : `--radius-sm|md|lg|full` · **Ombres** : `--shadow-sm|md|lg` +- **Layout** : `--container-max` (75rem) `--container-pad` (fluide 16→32) +- **Z-index** : `--z-nav|overlay|modal|toast` (100/200/300/400) +- **Motion** : `--dur-fast|base|slow` (150/250/400ms) · `--ease-out|in-out|spring` +- **Breakpoints** (constantes, PAS des variables) : 360 base · 480 sm · 768 md · 1024 lg · 1280 xl — media queries en rem, `min-width` only. + +Mode sombre : préférence système + `data-theme` explicite qui gagne dans les deux sens. Helper `window.tfSetTheme('light'|'dark'|'auto')` fourni par BaseLayout. + +### API des primitives (props → détail en tête de chaque fichier) + +| Primitive | Props | Slots | +|-----------|-------|-------| +| `BaseLayout.astro` | `title`* · `description` · `lang`('fr') · `ogImage` · `canonical` | default, header, footer, head | +| `Nav.astro` | `links: {href,label}[]`* · `label` | brand, actions | +| `Footer.astro` | — | default, legal | +| `Button.astro` | `variant: primary\|secondary\|ghost\|link` · `size: sm\|md\|lg` · `href` · `type` · `disabled` · `class` + attrs passthrough | default | +| `Card.astro` | `href` (carte cliquable + hover élévation) · `class` | media, default | +| `Prose.astro` | `class` | default (HTML long) | +| `Section.astro` | `alt` (fond alterné) · `size: base\|lg` · `id` · `class` | default | +| `Container.astro` | `size: base\|narrow` · `class` | default | +| `Reveal.astro` | `delay` (ms) · `class` | default | + +Utilitaire nu : `js/reveal.js` → `initReveal(selector?)`. + +### Consommation (rappel pour P2) + +```jsonc +// package.json du site +"dependencies": { "@transformer/ui": "git+https://git.trans-former.fr/jules/design-system.git" } +``` + +```astro +--- +import BaseLayout from "@transformer/ui/BaseLayout.astro"; +import "@transformer/ui/theme/tmip.css"; // ← le seul import qui change par site +--- +``` + +Fallback submodule + variante Tailwind 4 (racine) : voir `README.md`. Pont Tailwind : `tailwind.css` (`@theme inline`) — namespaces en collision non mappés, syntaxe `rounded-(--radius-md)` etc. (PROTOCOLE §4). + +## 2. Déviations vs brief + blockers + +- **Chemin local** : brief dit `C:\dev\` (Windows) ; la machine est Linux → repo dans `~/dev/design-system` (même logique hors-Dropbox, remote Gitea identique). +- **Ajout `@layer`** (pas dans le brief) : Astro inline le CSS des thèmes AVANT le `` du bundle tokens → l'ordre d'import ne suffisait pas. `tokens.css`→`@layer tf-tokens`, `reset.css`→`@layer tf-reset`, thèmes non-layerés → la cascade est correcte quel que soit l'ordre de bundling. Règle : ne jamais layerer un thème. +- **Ajout `tailwind.css`** (maj ligne 18 du brief) : pont `@theme inline` pour la racine. +- **Blockquote sans border-left** (loi Impeccable « border-left accent » prise au sens strict) : fond `--surface-2` + radius à la place. +- **Polices non embarquées** : les thèmes ne définissent que les stacks ; chaque site charge ses `@font-face` (la démo affiche donc les fallbacks système, pas Poppins/Open Sans). +- **BLOCKER P2** : palette TMIP inconnue → `theme/tmip.css` est un placeholder commenté. À remplir en P2 (procédure PROTOCOLE §5). + +## 3. Reste à faire pour P2 (migration TMIP) + +1. Confirmer la palette TMIP (clair + sombre) + couple de polices → remplir `theme/tmip.css`, ajouter `src/pages/demo/tmip.astro` (4 lignes), valider le kitchen sink. +2. Dans le repo TMIP : ajouter la dépendance `@transformer/ui`, remplacer le layout maison par `BaseLayout` + `Nav` + `Footer`, importer `theme/tmip.css`. +3. Dégraisser le `global.css` de TMIP : supprimer tout ce que tokens/reset/primitives couvrent ; le CSS restant = spécifique métier uniquement, zéro valeur en dur qui duplique un token. +4. Passer la Definition-of-Done (PROTOCOLE §7) : 360/768/1280, clair/sombre, reduced-motion, sans JS, clavier. +5. Tagger `v0.1.0` ici et épingler le tag côté TMIP si on veut du reproductible. + +## 4. Auto-audit — lois Impeccable + mobile-first + +**Vérifié (build + Puppeteer sur le build de prod)** : +- 3 pages démo × 3 viewports (360/768/1280) × clair/sombre = 18 combinaisons, **zéro overflow-x**. +- Hamburger : `aria-expanded` OK, Échap referme, focus revient au bouton, focus trap actif panneau ouvert. +- `prefers-reduced-motion: reduce` → reveals visibles d'office, kill-switch global dans le reset (`!important` layeré, imbattable). +- Sans JS → liens de nav visibles, rien de masqué (garde `html[data-js]`). +- Lois design : aucun border-left accent, aucun gradient text, pas de glassmorphisme, pas de hero-metric, pas de modal, pas d'auto-play. Ombres discrètes uniquement. +- Cibles tactiles : boutons/liens nav ≥ 44px ; `sm` remonte à 44px sur `pointer: coarse`. + +**Fragile / à surveiller** : +- **Contrastes AA vérifiés à l'œil et par calcul ponctuel, pas outillés** : passer un audit Lighthouse/axe sur la démo au prochain cycle (surtout `--text-subtle` sur `--bg-alt` et le jaune `--accent` renovation, utilisable seulement avec `--on-accent` dessus). +- Le pont Tailwind n'a **pas été testé contre un vrai build Tailwind 4** (aucun site Tailwind dans ce repo) → à valider en P3 sur `astro-site-cerveau`. +- `npm install git+https://…` non testé depuis un site consommateur réel (testé uniquement en local) → premier point à vérifier en P2 ; le fallback submodule est documenté si souci. +- La condensation de nav est discrète (padding) ; si un site veut un vrai shrink (logo qui réduit), l'étendre ICI, pas dans le site.