use_figma — Skill API Motion pour Figma Plugin
Contexte Motion pour l'outil MCP use_figma. figma-use couvre les règles foundationnelles de l'API Plugin — charge les deux ensemble.
Passe toujours skillNames: "figma-use-motion" (séparé par des virgules aux côtés de figma-use) lors de l'appel à use_figma pour du travail motion. Logging uniquement.
Runtime Gating
Les APIs Motion sont bloquées derrière le feature flag utilisateur metronome. Quand l'utilisateur qui appelle ne l'a pas, chaque propriété motion et helper référencé dans ce skill lève "<name>" is not a supported API.
Bats en retraite rapidement sur cette erreur. Ne réessaie pas ; dis à l'utilisateur que motion n'est pas activé pour lui et arrête. Sinon tu brûleras des appels et confondras l'utilisateur avec des échecs identiques répétés.
Quand utiliser ce skill
Charge ce skill chaque fois qu'une tâche use_figma implique :
- Ajouter, modifier ou supprimer des keyframes sur un nœud (
manualKeyframeTracks,applyManualKeyframeTrack,removeManualKeyframeTrack). - Animer les couleurs de remplissage ou de contour au fil du temps.
- Appliquer, modifier ou supprimer des styles d'animation (
applyAnimationStyle,removeAnimationStyle,animationStyles). - Lire ou écrire la durée de la timeline via
node.timelines/node.setTimelineDuration(id, seconds). - Choisir l'easing pour tout ce qui précède.
Le travail de design statique (créer des formes, des composants, des variables, de la mise en page) passe par figma-use seul — ce skill est uniquement pour la dimension temporelle.
Surface API motion exposée
node.manualKeyframeTracks— lire/écrire les keyframes manuelles (incluant les pistes de remplissage, contour et effet).node.applyManualKeyframeTrack(field, track)/node.removeManualKeyframeTrack(field)— ajouter, remplacer ou supprimer une piste de keyframe manuelle sans réécrire tout l'objet.node.animationStyles— lire/écrire les métadonnées de style d'animation appliquées à un nœud.node.applyAnimationStyle(styleId, presetData?)/node.removeAnimationStyle(id)— appliquer un style découvert et supprimer une instance de style appliqué par sonidretourné/relue.node.timelines— liste de timeline en lecture seule pour la frame top-level conteneur, avec durées en secondes.node.setTimelineDuration(id, durationSeconds)— écrire la durée de timeline de la frame top-level conteneur.node.animations— données de keyframe résolues en lecture seule (actuellement pistes manuelles uniquement — voir motion-patterns.md).figma.motion.figmaAnimationStyles()— liste en lecture seule des styles d'animation propriétaires de Figma.
Rédiger du code source de module preset custom "figma:motion" est hors de portée. Si l'utilisateur veut un style d'animation complètement nouveau, dis-le et arrête ; ne l'invente pas.
Docs de référence
Charge celles-ci selon les besoins en fonction de ce que la tâche implique :
| Doc | Quand charger | Couvre |
|---|---|---|
| motion-patterns.md | Ajouter/modifier une animation motion | Keyframes manuelles, remplissages/contours animés, appliquer des styles d'animation, durée de timeline |
| motion-easing.md | Définir l'easing d'animation | Objets d'easing de keyframe, cubic/spring custom, HOLD, appliquer l'easing dans un style d'animation |
Vérifier l'animation
get_screenshot affiche uniquement l'état au repos de la timeline, jamais le motion. Pour vérifier le motion, export_video et échantillonne les images — mais il rend côté serveur et est lent et coûteux (~10s à minutes), donc fais en sorte que chaque rendu compte.
Planifie avant de rendre — le coût évolue avec pixels × images, donc garde les deux pas plus grands que les frames ne le nécessitent :
- Choisis d'abord les moments. Tu as besoin d'une image par phase (p. ex. par étape de stagger, ou début / milieu / stabilisation), pas de lecture fluide — généralement 4–6. Ce nombre définit ton fps.
- Dimensionne à ce que tu dois lire. Commence petit —
constraint: { type: 'WIDTH', value: 320 },quality: "low"— mais le texte et les petits éléments deviennent flous là, donc augmenteWIDTH(768+) quand tu dois juger les détails fins. Omettreconstraint= taille complète (1x ; le serveur serre à 10x / 4096px). - Définis fps juste assez haut pour atteindre ces images :
fps: 5couvre une poignée ; 10 est une limite supérieure. Plus haut gonfle juste le rendu.
Mécaniques : export_video fonctionne uniquement sur une frame top-level dont les enfants portent l'animation (passe cette frame, pas le descendant que tu as keyframé). Il retourne un jobId avec status: "processing" — réinvoque avec { fileKey, jobId } pour faire du polling. Puis extrais les images localement avec ffmpeg -ss <t> -i anim.mp4 -frames:v 1 frame_<t>.png — l'extraction est gratuite, donc une fois que tu as payé le rendu, exploite-le pour chaque image qui te dit quelque chose plutôt que de ré-exporter. Sans un extracteur d'image comme ffmpeg, saute l'export et raisonne sur les keyframes à la place.
Itère jusqu'à ce que ce soit correct. L'export est un diagnostic, pas une validation : si les images sont mauvaises (mauvais ordre, timing désactivé, un élément manquant, un masque qui occulte le composite), corrige les keyframes/styles et ré-exporte. Lis toutes les images et regroupe chaque correction en un seul passage avant re-rendu — chaque rendu porte un vrai surcoût, donc fais en sorte que chacun compte au lieu de ré-exporter après chaque petit changement.
Saute l'export entièrement pour les changements triviaux ou évidents.
Liste de contrôle pré-décollage
En plus de la liste de contrôle pré-décollage figma-use, vérifie :
- [ ] L'easing utilise la forme publique
{ type: 'EASE_OUT', easingFunctionCubicBezier?: …, easingFunctionSpring?: … }— pas les noms internes du scenegraph commeOUT_CUBIC. - [ ] L'ease-in-out utilise l'enum public exact
EASE_IN_AND_OUT(ouEASE_IN_AND_OUT_BACK) ; n'émets jamais l'alias invalideEASE_IN_OUT. - [ ] Le nœud animé n'est pas une frame top-level (enfant direct d'une page). Anime les descendants à la place.
- [ ] Les valeurs de timeline sont en secondes dans l'API Plugin public. Étends via
setTimelineDuration; ne raccourcis jamais sauf si l'utilisateur a demandé. - [ ] Les champs de keyframe de transformation utilisent les noms publics (
TRANSLATION_X,TRANSLATION_Y,ROTATION,SCALE_X,SCALE_Y,SCALE_XY), pas les noms internes du scenegraphMOTION_*. - [ ] Les champs de keyframe manuels viennent de la liste d'autorisation publique dans motion-patterns.md ; les champs du scenegraph générés/internes lancent intentionnellement une erreur.
- [ ] Les IDs de nœud mutés sont retournés (par la Règle 15 de
figma-use). - [ ] Quand la correction du motion n'est pas évidente et qu'un extracteur d'image (
ffmpeg) est disponible, vérifie viaexport_video+ échantillonnage d'images — rends petit,fpsbas, itère jusqu'à ce que ce soit correct (voir la section Vérifier l'animation ci-dessus).get_screenshotaffiche uniquement l'état au repos.