Aller au contenu
§9.4

Motion Lab

La bibliothèque d'animations du projet, et la démonstration de chaque famille. Durées, courbes, décalages et distances viennent tous de src/styles/motion.css — aucune valeur n'est écrite dans un composant.

Règles de motion appliquées
TokenValeurUsage
Entrée420ms · ease-outReveal, Stagger, TextReveal
Survol160ms · ease-outBoutons, liens, cartes
Overlay240ms · ease-outModale, tiroir, popover
Transition de page240ms · ease-outOpacité + 8px, sans sortie
Stagger40 / 70 / 120msSerré, standard, ample
Course8 / 16 / 28pxAu-delà, cela lit comme un reflux de layout
A

Entrées

Reveal

motion/reveal.tsx
up
down
left
right

A11y — Sous prefers-reduced-motion, le composant rend l'état final sans transition : un élément ne peut pas rester invisible parce qu'un déclencheur de scroll n'est pas parti.

Stagger

motion/stagger.tsx
  • Premier
  • Deuxième
  • Troisième
  • Quatrième

A11y — L'orchestration vit sur le parent : les enfants ignorent leur index, on peut en ajouter ou en retirer sans retoucher les délais.

B

Texte

TextReveal

motion/text-reveal.tsx

Le mouvement doit renforcer la compréhension.

Chaque fragment monte sous un masque. La phrase reste lisible avant, pendant et après l'animation.

A11y — Le texte complet est dans le DOM en sr-only ; les fragments animés sont aria-hidden. Lecteurs d'écran et robots d'indexation lisent la phrase une fois, entière.

C

Survol et curseur

Magnetic

motion/magnetic.tsx

A11y — L'enveloppe animée n'est pas focusable : le bouton réel est son enfant, donc le clavier et le lecteur d'écran ne voient que lui. L'effet ne s'active que sur pointeur fin.

TiltCard

motion/tilt-card.tsx

Carte inclinée

Le ressort revient au repos à la sortie du pointeur.

A11y — Inclinaison plafonnée à 5°. Au-delà, le texte de la carte devient pénible à lire pendant le mouvement.

CursorFollow

motion/cursor-follow.tsx

Le halo suit le pointeur à l'intérieur de ce cadre, et seulement ici.

A11y — Décoratif : aria-hidden et pointer-events-none. Confiné à sa zone, jamais appliqué au curseur de la page entière.

D

Scroll

Parallax

motion/parallax.tsx

Faites défiler la page

A11y — Course totale de 28px sur la traversée du viewport. Faible par construction : au-delà, le décalage nuit à la lecture du texte posé dessus.

HorizontalRail

sections/horizontal-rail.tsx
H1

Défilement natif

scroll-snap et overflow-x: auto. Le geste tactile est celui du système, la zone est focusable au clavier.

H2

Pas de scroll détourné

Aucune conversion du scroll vertical en déplacement horizontal : c'est la première cause de pages qu'on n'arrive plus à quitter.

H3

Repère de fin

Le dernier élément affleure le bord pour signaler qu'il reste du contenu, sans barre de défilement personnalisée.

H4

Quand passer à GSAP

Lorsqu'une séquence doit synchroniser plusieurs timelines sur une même piste. Tant que ce n'est pas le cas, la dépendance ne se justifie pas.

A11y — Zone focusable avec role=region : les flèches du clavier défilent une fois la zone sélectionnée. Aucun détournement du scroll vertical.

E

Section épinglée

Le titre tient, le contenu passe

  1. 01

    Le scroll reste au navigateur

    La section est épinglée par position: sticky. La molette, le clavier et le geste tactile gardent leur comportement système ; rien n'intercepte le défilement.

  2. 02

    Motion lit, il ne pilote pas

    useScroll rapporte la progression dans la piste. Elle sert à faire varier l'opacité des étapes, pas à déplacer la page.

  3. 03

    La piste reste courte

    Sa hauteur est calculée sur le nombre d'étapes. Une section épinglée plus longue que quelques écrans donne l'impression que la page est bloquée.

F

Reduced motion

Le contrôle le plus important de cette page, et le seul dont l'échec est invisible en démonstration.

Ce qui est retiré

Toutes les transitions, tous les décalages, tous les stagger. m.css met les durées à 0,01ms et les distances à 0px en un seul endroit.

Ce qui est préservé

L'état final. Un composant ne rend jamais une version raccourcie de son animation : il rend le résultat.

Comment c'est vérifié

npm run verify charge la page avec reducedMotion: reduce et échoue si un titre reste sous une opacité de 0,9.