Implémenter Motion
Aperçu
Cette skill guide la traduction des animations et transitions Figma en code exécutable (motion.dev, CSS keyframes, ou libraries spécifiques au framework).
Figma expose motion via deux tools :
get_motion_context— outil motion autoritaire. Retourne l'inventaire complet des nœuds animés, les extraits de code précompilés (CSS@keyframes+ motion.dev), les liaisons de keyframe de secours quand les extraits ne sont pas disponibles, et les indices de coordination de timeline récursifs. Source de vérité pour les données d'animation et les ID de nœud qui s'animent.get_design_context— la structure du design : layout, dimensionnement, assets, styling, indices Code Connect, contexte screenshot, et parfois marqueurs de placement motion sur les éléments animés (data-node-id, et sur les nœuds fragmentésdata-motion-keys/data-motion-wrapper-for/data-motion-transform-template). Il peut afficher un nœud animé en tant qu'élément simple (div,p,span, etc.) ou élément motion (motion.div) ; il n'inline pas les valeurs d'animation.
Les deux sont liés par node id, et c'est tout le workflow. get_motion_context vous indique quels nœuds s'animent et fournit les valeurs keyframe, l'easing, le timing et les extraits. get_design_context vous indique à quoi ressemblent ces nœuds et où ils se situent. Pour chaque nœud dans get_motion_context.nodes, trouvez le data-node-id correspondant en contexte design et fusionnez le motion dans cette structure — en ajoutant ou enrobant un motion.{tag} quand l'élément structurel est simple. Quand le contexte design réutilise un composant Figma, le nœud motion peut aussi inclure fallbackNodeId ; utilisez-le uniquement en secours après avoir essayé l'exact nodeId.
Limites de la Skill
- Utilisez cette skill quand le livrable est du code motion dans le repository de l'utilisateur.
- Si l'utilisateur demande de créer/modifier des animations dans Figma lui-même, basculez vers figma-use et suivez cette skill à la place.
- Cette skill couvre actuellement les animations émises par
get_motion_context(extraits plus pistes keyframe de secours, incluant le motion créé par preset résolu dans ces formes). Les flux de variant interactifs plus larges peuvent encore nécessiter une gestion d'état spécifique au produit en code.
Prérequis
- Serveur MCP Figma connecté et accessible.
- Node ID analysé depuis l'URL Figma fournie par l'utilisateur. Format d'URL :
https://figma.com/design/:fileKey/:fileName?node-id=1-2— extrayezfileKey(le segment après/design/) etnodeId(la valeur du paramètre de requêtenode-id, par ex.42-15). - Codebase cible. Le format de sortie motion s'adapte à la stack (voir Recommandations Framework).
Choix des Tools
Pour l'implémentation motion, utilisez les deux tools avec des rôles distincts :
| Situation | Tool | Pourquoi |
|---|---|---|
| Comprendre la structure statique, les assets, les styles, Code Connect, ou le layout visuel | get_design_context |
Fournit la référence de code du composant/page et les URLs des assets dont vous avez besoin pour placer correctement les nœuds animés. |
| Récupérer les données d'animation pour n'importe quel nœud | get_motion_context |
Conçu pour motion et source de vérité pour le timing, l'easing, les extraits et les keyframes. |
Un nœud a des marqueurs motion (data-motion-keys, data-motion-wrapper-for) |
Marqueurs pour le placement fragmenté, get_motion_context pour les valeurs |
Les marqueurs fragmentés vous indiquent sur quel élément vont les pistes ; les keyframes/easing/timing et l'inventaire des nœuds animés viennent de get_motion_context. |
get_motion_context accepte recursive: true (plafonné à 500 nœuds) quand vous avez besoin du motion des descendants en un seul appel.
Workflow Requis
Étape 1 : Confirmer que le contexte design statique est disponible
get_design_context(fileKey=":fileKey", nodeId="<node-id>")
Si get_design_context a déjà été appelé pour ce nœud, réutilisez cette sortie. Sinon, appelez-le normalement maintenant.
Utilisez-le comme la structure de référence — hiérarchie, dimensionnement, styling, assets, indices Code Connect, contexte screenshot, et tous marqueurs motion qu'il pourrait inclure (Étape 3). L'inventaire des nœuds animés et les valeurs d'animation viennent de get_motion_context (Étape 2).
Étape 2 : Récupérer les données motion autoritaires
get_motion_context(fileKey=":fileKey", nodeId="<node-id>", recursive=true)
Forme de réponse (une entrée par nœud animé) :
codeSnippets— chaînes CSS@keyframeset motion.dev pré-générées. Utilisez-les directement. Ne les régénérez pas à partir des données de piste de secours.keyframeBindings— pistes keyframe liées, incluant le motion dérivé de preset résolu en données de piste, inclus uniquement comme données de secours quand les deux formats d'extrait manquent.fallbackNodeId— id de secours optionnel pour correspondre au contexte design componentisé. SinodeIdest un id qualifié d'instance commeI4005:6111;30:8005, D2R peut afficher le corps du composant réutilisable avec l'id du composant de support à la place, comme4002:3957. Dans ce cas,fallbackNodeIdest ledata-node-idà chercher si la recherche exactnodeIdéchoue.
Les réponses récursives peuvent aussi inclure timelineCohorts : groupes d'IDs de nœuds animés qui partagent une racine timeline, une durée et un mode de lecture (once, loop, ou boomerang). Utilisez les cohorts pour garder les animations décalées ou multi-nœuds synchronisées au lieu d'inférer le timing partagé à partir de l'ordre des frères.
Détails d'implémentation qui importent pour les LLMs :
- Quand les extraits existent, les
keyframeBindings,timelineDurationMs,motionSummarybruts ettransformOriginpar défaut peuvent être supprimés pour réduire la taille du payload. L'absence dekeyframeBindingsn'est pas un signal qu'il n'y a pas d'animation. - Les réponses récursives dédupliquent les extraits exactement dupliqués. Un extrait peut être remplacé par un commentaire pointant vers le premier nœud avec motion identique ; réutilisez le même composant, variant, classe ou constantes au lieu d'écrire une deuxième animation.
- Le serveur MCP déduit les extraits CSS vs motion.dev de
clientFrameworks; si la réponse ne contient qu'un seul format d'extrait, adaptez ce format à la stack de l'utilisateur plutôt que de supposer que l'autre format a échoué.
Étape 3 : Fusionner le contexte statique et motion
- Commencez par
get_motion_context.nodes, pas à partir des tags visiblesmotion.*dans le JSX statique. Chaque nœud retourné est animé. Faites correspondre chaque nœud motion àget_design_contextparnodeId/data-node-idexact en premier. Si et seulement s'il n'y a pas de correspondance exacte, essayezfallbackNodeId/data-node-id. Basculez vers le nom/type du nœud et la position du screenshot seulement après l'échec des deux ids. - La correspondance id exacte l'emporte sur
fallbackNodeId.fallbackNodeIdpointe vers l'id du composant de support que D2R peut émettre dans un composant réutilisable. Il est partagé par chaque instance de ce composant. Si l'exactnodeIdexiste en contexte design, appliquez le motion là et ignorez le secours. C'est critique pour l'animation root-instance : une instance peut tourner ou se déplacer différemment d'une autre instance du même composant, et appliquer ce motion au corps du composant partagé animerait toutes les instances incorrectement. - Appliquez chaque nœud motion à la structure du contexte design correspondante, indexée par
data-node-id. Ledata-node-idcorrespondant est l'ancre structurelle, pas toujours l'élément DOM final qui reçoit le motion. Utilisez la forme d'extrait et les marqueurs de placement pour décider si le motion va sur cet élément exact, un wrapper, un élément interne, ou un chemin SVG inliné.get_design_contextpeut déjà émettremotion.{tag}avec les valeurs supprimées, ou il peut émettre un élément structurel simple (div,p,span, racine de composant, etc.). S'il est simple et que l'extrait cible l'élément lui-même, convertissez-le enmotion.{tag}approprié ou ajoutez un wrapper motion tout en préservant le texte, les enfants, les classes/styles, les attributs et ledata-node-iddu nœud. Chargez references/examples-and-anti-examples.md pour voir des exemples de cette étape de fusion. - Le motion des enfants componentisés correspond généralement par secours. Quand le contexte design extrait une instance Figma dans un composant React réutilisable, les enfants dans le corps du composant ont souvent des ids de composant de support (
4002:3957) tandis que le contexte motion rapporte des ids d'instance en direct (I4005:6111;30:8005). Dans ce cas, utilisezfallbackNodeIdpour trouver ledata-node-iddu corps du composant, mais gardez le motion limité à l'instance rendue que vous implémentez. S'il y a plusieurs instances et qu'une seule a un motion root différent, la correspondance id exacte garde ce motion par instance séparé. - Les nœuds fragmentés portent un marqueur
data-motion-keys/data-motion-wrapper-for— voir Gérer les transforms interleaved ci-dessous. - Préservez les wrappers
display: contents— sauf si le groupe lui-même s'anime. Les wrappers de groupe transparents pour le layout viennent commecontents(Tailwindcontents), généralement aux côtés d'unabsolute/inset-[…]mort (ceux ne font rien sur une boîtecontents). Pour un groupe statique, gardezdisplay: contentset laissez les enfants se positionner contre l'ancêtre réel le plus proche — convertir leinsetdu wrapper en boîte positionnée reparente les enfants vers une boîte plus petite, donc ils affichent trop petit / décalés vers l'intérieur. Pour un groupe animé (le nœud du groupe lui-même a du motion),display: contentsne peut pas porter un transform — remplacez-le par un wrapper réel positionné et appliquez le motion du groupe là. Chargez references/gotchas.md avant d'implémenter ce cas. get_motion_contextest l'inventaire complet des nœuds animés. Certains nœuds animés affichent comme des éléments simples (nonmotion) — racines d'instance de composant (div simple positioning), texte (<p>), masques — qui portent toujours undata-node-id. Parcourez chaque nœud dans la réponse motion et appliquez son motion à l'élément avec ledata-node-idcorrespondant, enrobant ou convertissant au besoin. Si un nœud animé n'a aucun élément du tout dans la sortie (par ex. un masque animé aplati dans unmask-imagestatique), ne le supprimez pas silencieusement — laissez un commentaire// TODO: <nodeId> motion unsupportedet signalez-le dans votre résumé.- Si un nœud apparaît en contexte motion mais pas dans le JSX statique, ajoutez l'élément nécessaire pour le représenter — le code du contexte design est une référence, pas un inventaire d'animation complet.
- En cas de conflit entre le contexte design et motion (timing/easing/valeurs animées), préférez
get_motion_context. - Motion SVG au niveau du chemin : inlinisez le SVG et animez le vrai
<path>. Quandget_motion_contextcible le chemin d'un vecteur (PATH_TRIM,motion.path,stroke-dasharray) mais que le contexte design l'affiche en tant que<img>, inlinisez le SVG et appliquez l'extrait au<path>, en gardant le wrapper de layout. Chargez references/svg-and-path-motion.md pour la procédure complète pour ce cas (motion.path,pathLength="1", wrapper+path layering, CSS path-trim).
Gérer les transforms interleaved
Un nœud avec à la fois un transform statique de base et des transforms animés est fragmenté sur des éléments imbriqués pour que les deux se composent correctement au lieu de se combattre : un motion.div sans id portant data-motion-wrapper-for="<nodeId>" (le wrapper EXTERNE) enveloppe un div de transform statique (par ex. rotate-45 + sizing hypot() — ou le wrapper lui-même porte data-motion-transform-template="<css>") qui enveloppe le nœud INTERNE (data-node-id). Gardez l'imbrication wrapper > static-transform div > inner — l'aplatir casse le dimensionnement et le transform de base.
- Placez les pistes par
data-motion-keys. Lesdata-motion-keysdu wrapper (pistes transform —x/y/rotate/scaleX/scaleY/skewX) vont sur le wrapper EXTERNE ; lesdata-motion-keysde l'élément interne vont sur l'élément INTERNE. - Réappliquez un
data-motion-transform-template. Si le wrapper en porte un, définisseztransformTemplate={(_, generated) => "<css> " + generated}pour que le transform animé se compose sur ce transform layout statique. - Décalez le transform animé par la base statique (évitez la rotation double).
get_motion_contextdonne le transform absolu du nœud, qui inclut déjà le transform statique de base que ces divs appliquent. Un extraitrotatede[45, 125, 125]sur une baserotate-45signifie que le wrapper anime l'offset[0, 80, 80](= absolu − 45), pas l'absolu — sinon le 45° s'applique deux fois et l'élément s'assoit à 90° au repos. Les pistes sans base statique (par ex.x/ycommençant à 0) passent inchangées. Voir l'exemple interleaved-transform. - Gardez les transforms layout séparés des transforms Motion. Pour chaque élément
motion.*qui animerotate,scale, ouskew, vérifiez qu'il ne repose pas aussi sur les transforms layout Tailwind comme-translate-x-1/2ou-translate-y-1/2pour le centrage/positionnement. Ces utilitaires partagent la propriété CSStransformque Motion.dev écrit inline, donc le transform de Motion peut effacer le layout translate. Si les deux sont nécessaires, fragmentez l'élément en un wrapper layout statique portant le transform centrage/positionnement et un élémentmotion.*interne portant le rotate/scale/opacity animé, ou encodez l'offset layout dans Motion lui-même (x: "-50%") et gardez-le présent pour chaque keyframe.
Étape 4 : Appliquer le motion en code
- motion.dev présent dans les extraits ? Utilisez le code motion.dev verbatim pour les cibles React. Importez de
motion/react— sauf si la codebase utilise déjà une autre library motion (Framer Motion, React Spring, GSAP), auquel cas adaptez l'extrait. Chargez references/framework-recommendations.md quand vous adaptez à une autre stack ou choisirez une library. - CSS keyframes présent ? Utilisez pour les cibles vanilla/non-React, ou quand la codebase n'a pas de library motion React.
- Pas d'extraits ? Utilisez
keyframeBindingsoumotionSummarycomme données de secours pour construire des appels motion.dev équivalents ou des CSS keyframes. Normalement les extraits sont présents ; faites cela seulement quand les deux formats d'extrait manquent vraiment.
Étape 5 : Valider
- Lisez les importations motion et conventions existantes du composant avant d'en ajouter de nouvelles. Si l'utilisateur utilise déjà Framer Motion / React Spring / anime.js, adaptez plutôt que de forcer motion.dev.
- Vérifiez de bout en bout qu'une animation s'exécute (rechargez, observez, itérez) avant de regrouper les modifications sur plusieurs nœuds.
- Chargez references/gotchas.md, qui couvre les bugs spécifiques à Figma motion et leurs fixes, et corrigez les cas pertinents dans le code généré.
Règles Critiques
Ce sont les principes généraux. Les gotchas spécifiques (pivots de rotation, sémantique HOLD, interpolation de couleur, etc.) vivent dans les références catégorisées. Quand une référence liée est mentionnée dans ce texte de skill et que la situation s'applique, chargez ce fichier avant de continuer.
- Respectez les valeurs de la sortie du tool, pas son layout. Préservez le timing exact, l'easing, les valeurs keyframe et
transformOrigindescodeSnippets— ne les régénérez pas à partir dekeyframeBindingsquand les extraits existent (régénérer perd la fidélité sur les bezier easing personnalisés, les approximations spring et les valeurs d'overshoot).transformOriginest par élément : appliquez le vôtre pour chaque nœud scaling/rotating — incluant les scalers imbriqués, pas juste le wrapper externe — ou l'élément pivote du center par défaut et grandit/tourne depuis le mauvais coin (voir l'exemple per-element-transformOrigin). Mais l'extrait est les données d'un nœud, pas un template copy-paste : quand plusieurs nœuds le partagent, factorisez-le par Règle 7 au lieu de coller le bloc N fois. - Correspondez à la stack motion existante de l'utilisateur. Lisez les importations du composant et les animations frères avant d'ajouter des dépendances. Si l'utilisateur a déjà Framer Motion, React Spring, anime.js, GSAP — adaptez la sortie à leur stack plutôt que de forcer motion.dev.
- Honorer
prefers-reduced-motion. N'importe quel motion ajouté doit s'adoucir ou se désactiver sous@media (prefers-reduced-motion: reduce)— généralement passer leanimate(afficher l'état initial/repos) ou couper la durée à près de zéro. C'est une valeur par défaut d'accessibilité, pas un opt-in. - Valider une animation de bout en bout avant de regrouper. Construisez, rechargez et regardez une boucle timeline complète — confirmez que chaque nœud animé apparaît à l'heure que sa piste keyframe dit qu'il devrait. « Affiche sans erreur » n'est pas « affiche correctement ». Les défaillances motion se cumulent quand vous regroupez — un mauvais easing sur un nœud est facile à voir ; le même bug sur vingt nœuds est des heures de démêlement.
- Ne fabriquez pas de motion. Si un nœud n'a pas de données motion dans la réponse, laissez-le statique. N'empruntez pas les defaults d'easing/duration d'ailleurs dans le design, et n'auto-animez pas « parce que le reste du composant est animé ».
- Ne téléchargez pas un asset juste pour le
Read.get_design_context/get_motion_contextretournent les assets comme URLs (/api/mcp/asset/...), souvent SVG. Référencez l'URL directement où le consommateur la récupère (un<img src>, CSSbackground-image, une importation d'asset), oucurlune pour inliner son contenu (par ex. inlinisez le SVG et affichez viaNSImage(data:)sur SwiftUI). L'exception importante est le motion SVG au niveau du chemin : si l'extrait motion cible un chemin à l'intérieur d'un asset SVG, inlinisez le SVG et animez le vrai chemin au lieu de le laisser derrière un<img>. Ne téléchargez pas un asset et ne le passez pas au toolRead: SVG n'est pas un format d'image lisible, donc la lecture est rejetée et gaspillée — et un file tool qui ne détecte pas SVG-as-image peut bloquer la boucle dessus. - Factorisez le motion répété — ne copiez-collez jamais l'extrait par élément. Plusieurs nœuds partagent généralement la même animation différant seulement par un délai de stagger, un offset ou une valeur cible. Implémentez le motion partagé une fois — un composant animé réutilisable ou un objet
variantsparamétrisé par les valeurs qui varient — rendez d'un array mappé (items.map(...)), et tirez les littéraux répétés (durées, tableaux easing, offsets) dans les constantes nommées. Les valeurs de l'animation restent verbatim de l'extrait (Règle 1) ; le code reste DRY. Le même objet transition collé 15+ fois (800 lignes qui devraient en être 150) est un résultat de basse qualité — la fidélité et la maintenabilité sont toutes deux évaluées.
Recommandations Framework
La Règle 2 couvre la posture générale : préférez la stack existante de l'utilisateur. Quand aucune n'existe, defaults :
- React : motion.dev (le package
motion). Le tool retourne le code motion.dev directement — utilisez-le. - Vanilla / web non-React : CSS
@keyframesavec shorthandanimation, retournés directement par le tool. - SwiftUI : Modifieurs natifs
.animation(...); traduisez à partir des extraits,keyframeBindings, oumotionSummary(get_motion_contextn'émet pas du code SwiftUI). Utilisez seulement les APIs SwiftUI réelles — il n'y a pas de modifier qui prend un type easing Figma/CSS directement, donc chargez references/framework-recommendations.md, mappez l'easing émis à son équivalent SwiftUI, et vérifiez plutôt que d'inventer une méthode. Ce chemin évolue ; confirmez avec l'utilisateur si doute.
Pour les classes d'effet établies, préférez une library plutôt que du CSS maison. Les effets comme glass/glassmorphism, confetti, systèmes de particules, interactions basées sur la physique et le motion lié au scroll ont des implémentations de library éprouvées en combat qui gèrent les quirks cross-browser, l'accessibilité et la performance bien mieux que les keyframes générés. Chargez references/framework-recommendations.md pour la table complète library-par-classe-d'effet. Présentez-les comme des recommandations, pas des mandats — l'utilisateur décide.
Exemples
Chargez references/examples-and-anti-examples.md quand vous avez besoin d'exemples travaillés ou de patterns de défaillance. Cela couvre le flux de fusion simple, les éléments texte simples qui ont besoin de motion.* ajouté, les transforms statique+animé interleaved, le motion SVG au niveau du chemin, et les anti-exemples pour la reconstruction DOM, la dérive node-id/position, et le transformOrigin manquant par élément.
Références
Six deep dives, récupérés sur demande. Les concerns générales du frontend (performance, unités, mécanique d'accessibilité) sont traitées par les règles critiques ci-dessus — ces références se concentrent seulement sur le signal spécifique à Figma. Si cette skill nomme l'un de ces fichiers dans une instruction inline, chargez ce fichier avant de continuer avec cette partie de la tâche.
- references/examples-and-anti-examples.md — exemples travaillés et patterns de défaillance. Chargez quand vous appliquez le workflow de fusion, gérez les transforms interleaved, ou vérifiez si une implémentation générée a reconstruit le DOM, échangé les positions de nœud, ou supprimé
transformOrigin. - references/gotchas.md — bugs de motion spécifiques à Figma et leurs fixes. Rotation/scale origin sur les groupes imbriqués, sémantique HOLD easing, préservation CUSTOM_SPRING, ambiguïté d'échelle d'axe indépendant, interpolation de couleur. Chargez quand vous résolvez un comportement runtime inattendu. Chargez toujours references/motion-lint-rules.md aux côtés de ce fichier — les entrées gotcha font référence à des règles lint spécifiques qui doivent être signalées à l'utilisateur.
- references/svg-and-path-motion.md — implémenter le motion qui cible un chemin d'un vecteur SVG (inlinisez l'asset,
motion.path,pathLength="1", wrapper+path layering, CSS path-trim). Chargez quand le snippet d'un vecteur cible le chemin, pas un wrapper transform. - references/framework-recommendations.md — motion.dev, CSS keyframes, defaults SwiftUI, table library-par-classe-d'effet (glass, confetti, particles, physics, scroll-linked). Chargez avant de coder en dur un effet.
- references/unsupported-and-fallbacks.md — Fonctionnalités Figma motion qui ne s'exportent pas proprement aujourd'hui (text animations, path animations, masks/booleans, variants/transitions). Inclus la guidance fallback video/lottie. Chargez quand la réponse du tool semble incomplète. Chargez toujours references/motion-lint-rules.md aux côtés de ce fichier — les entrées unsupported font référence à des règles lint spécifiques qui doivent être signalées à l'utilisateur.
- references/motion-lint-rules.md — Règles de linting : limitations d'export connues (erreurs et avertissements) qui doivent être signalées à l'utilisateur. Chargez quand vous générez du code motion pour vérifier si des limitations actives s'appliquent.