Communitygithub.com

motion-foundations

Jetons de mouvement, préréglages de ressort, règles de performance, adaptation aux appareils, application de l’accessibilité et sécurité SSR pour React / Next.js avec motion/react. Couche fondamentale – toutes les autres compétences de mouvement en dépendent. À utiliser lors de la mise en place de jetons de mouvement, de préréglages de ressort, de la gestion du mouvement réduit ou d’animations sans risque SSR dans React ou Next.js.

Qu'est-ce que motion-foundations ?

Cette compétence établit la couche de base du système de mouvement pour React et Next.js avec `motion/react`. Elle définit tous les jetons (durée, easing, distance, échelle), les préréglages de ressort nommés, et une fonction `shouldAnimate()` centralisée qui vérifie les préférences de mouvement réduit et les capacités de l’appareil. La compétence impose des règles strictes : utiliser exclusivement `motion/react`, éviter les animations sur les propriétés de layout, et garantir la sécurité SSR en faisant correspondre l’état `initial` au rendu serveur. Elle fournit également des hooks d’accessibilité comme `useSafeMotion` et un système de tokens typé. Cela en fait la fondation indispensable sur laquelle reposent les compétences `motion-patterns` et `motion-advanced`.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/motion-foundations

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Fondations du Mouvement

La couche de base du système de mouvement. Définit chaque valeur, contrainte et règle que les compétences en aval (motion-patterns, motion-advanced) héritent. Chargez cette compétence avant tout travail d'animation.

Quand l'Activer

  • Démarrer un composant animé de zéro
  • Mettre en place des jetons, des préréglages de ressort ou des valeurs d'easing
  • Implémenter la prise en charge de prefers-reduced-motion
  • Déboguer les décalages d'hydratation causés par les états initiaux d'animation
  • Évaluer si une animation devrait exister

Résultats

Cette compétence produit :

  • Un objet motionTokens partagé (durée, easing, distance, échelle)
  • Une carte de préréglages springs partagée (5 configurations nommées)
  • Une fonction shouldAnimate() utilisée par tous les composants
  • Des valeurs par défaut d'animation conformes à l'accessibilité via useReducedMotion
  • Des états initiaux sécurisés pour SSR sans avertissements d'hydratation

Principes

Le mouvement doit faire au moins l'une des choses suivantes, sinon il doit être supprimé :

  • Guider l'attention
  • Communiquer un état
  • Préserver la continuité spatiale

La réactivité prime toujours sur la fluidité. Une animation à 60 ips qui entraîne un délai de saisie est pire qu'aucune animation.

Règles

Elles sont non-négociables. Elles s'appliquent à chaque composant du système.

  1. Utilisez motion/react uniquement. N'importez jamais depuis framer-motion. Ne mélangez jamais les deux dans le même arbre.
  2. initial doit correspondre au rendu serveur. Si le serveur rend opacity: 1, la prop initial doit aussi être opacity: 1. Aucune exception.
  3. Le mouvement réduit prévaut sur tout. Quand useReducedMotion() renvoie true ou que prefersReduced est true, toutes les transformations sont désactivées. Les fondus d'opacité uniquement d'une durée ≤ 0,2s sont la seule solution de repli autorisée.
  4. N'animez jamais les propriétés de layout. width, height, top, left, margin, padding sont interdits dans animate. Utilisez uniquement transform et opacity.
  5. Toutes les valeurs de jetons proviennent de motionTokens. Les durées et easings en dur dans les fichiers de composants sont interdits.
  6. Toutes les configurations de ressort proviennent de la carte springs. Les valeurs stiffness/damping en ligne sont interdites.
  7. "use client" est obligatoire sur chaque fichier qui importe depuis motion/react.
  8. Ne lisez jamais window ou navigator au niveau du module. Protégez toujours avec typeof window !== "undefined".

Guide de Décision

Choisir une durée

JetonÀ utiliser quand
instantAffichage/masquage d'infobulle, anneau de focus, mise à jour de badge
fastRetour de bouton, changement d'icône, bascule de chip
normalOuverture de modale, agrandissement de carte, entrée d'élément de page
slowEntrée de héros, transition de page entière
crawlNarration délibérée ; à utiliser avec parcimonie

Choisir un ressort

PréréglageÀ utiliser quand
snappyUI par défaut — boutons, chips, éléments de navigation
gentleCartes, modales, panneaux qui se posent en douceur
bouncyMoments ludiques — états vides, intégration
instantInfobulles, popovers, menus déroulants
releaseRelâchement de glisser-déposer — sensation physique naturelle

Quand désactiver complètement l'animation

Désactivez (faites en sorte que shouldAnimate() renvoie false) quand :

  • prefersReduced est true
  • isLowEnd est true et l'animation n'est pas essentielle
  • L'élément est hors écran et n'entrera jamais dans la fenêtre
  • L'animation est purement décorative sans objectif UX

Concepts Fondamentaux

Système de jetons

// lib/motion-tokens.ts
export const motionTokens = {
  duration: {
    instant: 0.08,
    fast:    0.18,
    normal:  0.35,
    slow:    0.6,
    crawl:   1.0,
  },
  easing: {
    smooth: [0.22, 1, 0.36, 1],
    sharp:  [0.4, 0, 0.2, 1],
    bounce: [0.34, 1.56, 0.64, 1],
    linear: [0, 0, 1, 1],
  },
  distance: {
    xs: 4,
    sm: 8,
    md: 16,
    lg: 24,
    xl: 48,
  },
  scale: {
    subtle: 0.98,
    press:  0.95,
    pop:    1.04,
  },
}

export const springs = {
  snappy:  { type: "spring", stiffness: 300, damping: 30 },
  gentle:  { type: "spring", stiffness: 120, damping: 14 },
  bouncy:  { type: "spring", stiffness: 400, damping: 10 },
  instant: { type: "spring", stiffness: 600, damping: 35 },
  release: { type: "spring", stiffness: 200, damping: 20, restDelta: 0.001 },
}

Indicateurs d'exécution

// lib/motion-config.ts
export const motionConfig = {
  isLowEnd() {
    return (
      typeof navigator !== "undefined" &&
      navigator.hardwareConcurrency <= 4
    )
  },

  prefersReduced() {
    return (
      typeof window !== "undefined" &&
      window.matchMedia("(prefers-reduced-motion: reduce)").matches
    )
  },

  shouldAnimate({ essential = false } = {}) {
    if (this.prefersReduced()) return false
    if (!essential && this.isLowEnd()) return false
    return true
  },

  duration() {
    return this.isLowEnd() || this.prefersReduced()
      ? motionTokens.duration.instant
      : motionTokens.duration.normal
  },
}

Accessibilité

Ordre de priorité (du plus élevé au plus bas) :

  1. prefers-reduced-motion: reduce — désactive toutes les transformations, limite les transitions d'opacité à ≤ 0,2s
  2. Détection d'appareil bas de gamme — réduit la durée, supprime les animations non essentielles
  3. Préférence de conception — tout le reste

Le mouvement doit se dégrader gracieusement. Il ne doit jamais disparaître brusquement d'une manière qui provoque un décalage de mise en page ou désoriente l'orientation.

// hooks/use-reduced-motion.tsx
"use client"
import { useReducedMotion } from "motion/react"

export function useSafeMotion(fullY: number = 16) {
  const reduce = useReducedMotion()
  return {
    initial: { opacity: 0, y: reduce ? 0 : fullY },
    animate: { opacity: 1, y: 0 },
    exit:    { opacity: 0, y: reduce ? 0 : -fullY },
  }
}
/* globals.css */
@media (prefers-reduced-motion: reduce) {
  .motion-safe-transition  { transition: opacity 0.15s; }
  .motion-reduce-transform { transform: none !important; }
}
<!-- Tailwind -->
<div class="motion-safe:animate-fade motion-reduce:opacity-100"></div>

Sécurité SSR / Hydratation

Règle : initial doit toujours correspondre à ce que le serveur rend.

// FAUX — le serveur rend opacity:1 mais initial dit 0 → décalage d'hydratation
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} />

// CORRECT — utiliser AnimatePresence ou différer au montage client
"use client"
const [mounted, setMounted] = useState(false)
useEffect(() => setMounted(true), [])

<motion.div
  initial={{ opacity: mounted ? 0 : 1 }}
  animate={{ opacity: 1 }}
/>

Exemples de Code

De bout en bout : jetons + ressorts + accessibilité + garde SSR

// components/fade-in-card.tsx
"use client"

import { useState, useEffect } from "react"
import { motion } from "motion/react"
import { motionTokens, springs } from "@/lib/motion-tokens"
import { useSafeMotion } from "@/hooks/use-reduced-motion"
import { motionConfig } from "@/lib/motion-config"

interface FadeInCardProps {
  children: React.ReactNode
  delay?: number
}

export function FadeInCard({ children, delay = 0 }: FadeInCardProps) {
  // Garde SSR — initial doit correspondre à la sortie du serveur (opacity: 1)
  const [mounted, setMounted] = useState(false)
  useEffect(() => setMounted(true), [])

  // Accessibilité — désactive la transformation quand le mouvement réduit est préféré
  const safeMotion = useSafeMotion(motionTokens.distance.md)

  // Barrière d'appareil — saute l'animation sur le matériel bas de gamme
  if (!motionConfig.shouldAnimate() || !mounted) {
    return <div>{children}</div>
  }

  return (
    <motion.div
      initial={safeMotion.initial}
      animate={safeMotion.animate}
      exit={safeMotion.exit}
      transition={{
        ...springs.gentle,
        delay,
      }}
      whileHover={{ scale: motionTokens.scale.pop }}
      whileTap={{ scale: motionTokens.scale.press }}
    >
      {children}
    </motion.div>
  )
}

Contraintes / Hors Périmètre

Cette compétence ne couvre pas :

  • Les motifs de composants UI (bouton, modale, décalage) → voir motion-patterns
  • Le glisser-déposer, les gestes, SVG, les animations de texte, les hooks personnalisés → voir motion-advanced
  • Les animations uniquement CSS ou les classes Tailwind animate-* sans motion/react
  • Les bibliothèques d'animation tierces (GSAP, anime.js, etc.)
  • Les décisions de conception de mouvement (quand animer, quoi mettre en valeur) — c'est une préoccupation de conception, pas une contrainte de code

Anti-Patterns

Anti-patternRègle violéeCorrectif
import { motion } from "framer-motion"Règle 1Utilisez motion/react
initial={{ opacity: 0 }} sur un composant SSRRègle 2Ajoutez une garde de montage
Ignorer la vérification useReducedMotionRègle 3Utilisez le hook useSafeMotion
animate={{ width: "100%" }}Règle 4Utilisez plutôt la transformation scaleX
transition={{ duration: 0.4 }} en ligneRègle 5Utilisez motionTokens.duration.normal
{ stiffness: 300, damping: 30 } en ligneRègle 6Utilisez springs.snappy
Directive "use client" manquanteRègle 7Ajoutez en haut du fichier
navigator.hardwareConcurrency au niveau du moduleRègle 8Enveloppez avec typeof navigator !== "undefined"

Compétences Connexes

  • motion-patterns — consomme les jetons et ressorts définis ici pour construire des motifs de bouton, modale, décalage, transition de page et défilement. Ne redéfinit aucune valeur.
  • motion-advanced — consomme les jetons et ressorts définis ici pour les motifs de glisser-déposer, SVG, texte et gestes. Ajoute des séquences useAnimate et des hooks personnalisés par-dessus cette fondation.

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

Skills associés