Communitygithub.com

motion-foundations

Tokens de movimiento, presets de resorte, reglas de rendimiento, adaptación de dispositivos, cumplimiento de accesibilidad y seguridad SSR para React/Next.js usando motion/react. Capa base: todas las demás habilidades de motion dependen de esta. Úsalo al configurar tokens de movimiento, presets de resorte, manejo de movimiento reducido o animación segura para SSR en React o Next.js.

¿Qué es motion-foundations?

Motion Foundations es la capa base del sistema de animación motion/react. Define todos los valores, restricciones y reglas que heredan las habilidades secundarias (`motion-patterns`, `motion-advanced`). Debe cargarse antes de comenzar cualquier trabajo de animación. Proporciona un objeto compartido `motionTokens` (duración, easing, distancia, escala), un mapa de presets de resortes (`springs`) con 5 configuraciones con nombre, una puerta `shouldAnimate()` utilizada por todos los componentes, valores predeterminados de animación accesibles mediante `useReducedMotion` y estados iniciales seguros para SSR sin advertencias de hidratación. La habilidad establece principios no negociables: solo usar `motion/react`, evitar animar propiedades de layout, usar solo `transform` y `opacity`, y garantizar que `initial` coincida con la salida del servidor. Además, incluye guías de decisión para elegir duraciones y resortes, detección de dispositivos de gama baja, manejo de `prefers-reduced-motion` y ejemplos de código completos que integran tokens, resortes, accesibilidad y protección SSR. Está diseñada para React y Next.js, y es esencial para cualquier proyecto que busque animaciones consistentes, accesibles y de alto rendimiento.

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

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Motion Foundations

La capa base del sistema de movimiento. Define cada valor, restricción y regla que heredan las habilidades secundarias (motion-patterns, motion-advanced). Carga esta habilidad antes de comenzar cualquier trabajo de animación.

Cuándo activarla

  • Al comenzar cualquier componente animado desde cero
  • Al configurar tokens, presets de resorte o valores de easing
  • Al implementar soporte para prefers-reduced-motion
  • Al depurar discrepancias de hidratación causadas por estados iniciales de animación
  • Al evaluar si una animación debería existir

Salidas

Esta habilidad produce:

  • Un objeto motionTokens compartido (duración, easing, distancia, escala)
  • Un mapa de presets springs compartido (5 configuraciones con nombre)
  • Una puerta shouldAnimate() utilizada por todos los componentes
  • Valores predeterminados de animación accesibles mediante useReducedMotion
  • Estados iniciales seguros para SSR sin advertencias de hidratación

Principios

El movimiento debe cumplir al menos uno de los siguientes, o debe eliminarse:

  • Guiar la atención
  • Comunicar estado
  • Preservar la continuidad espacial

La capacidad de respuesta siempre prevalece sobre la fluidez. Una animación de 60 fps que causa retraso en la entrada es peor que ninguna animación.

Reglas

Estas no son negociables. Se aplican a todos los componentes del sistema.

  1. Usa solo motion/react. Nunca importes desde framer-motion. No mezcles ambos en el mismo árbol.
  2. initial debe coincidir con la salida del servidor. Si el servidor renderiza opacity: 1, la prop initial también debe ser opacity: 1. Sin excepciones.
  3. El movimiento reducido lo anula todo. Cuando useReducedMotion() devuelve true o prefersReduced es true, todas las transformaciones están deshabilitadas. Solo se permiten fundidos de opacidad de ≤ 0.2 s.
  4. Nunca animar propiedades de layout. width, height, top, left, margin, padding están prohibidas en animate. Usa solo transform y opacity.
  5. Todos los valores de token provienen de motionTokens. Las duraciones y easings hardcodeados en archivos de componente están prohibidos.
  6. Todas las configuraciones de resorte provienen del mapa springs. Los valores inline de stiffness/damping están prohibidos.
  7. "use client" es obligatorio en cada archivo que importe de motion/react.
  8. Nunca leas window o navigator a nivel de módulo. Siempre protege con typeof window !== "undefined".

Guía de decisión

Elegir una duración

TokenUsar cuando
instantMostrar/ocultar tooltip, anillo de enfoque, actualización de badge
fastRetroalimentación de botón, cambio de icono, alternancia de chip
normalApertura de modal, expansión de tarjeta, entrada de elemento de página
slowEntrada de héroe, transición de página completa
crawlNarración deliberada; usar con moderación

Elegir un resorte

PresetUsar cuando
snappyUI predeterminado: botones, chips, elementos de navegación
gentleTarjetas, modales, paneles que aterrizan suavemente
bouncyMomentos lúdicos: estados vacíos, incorporación
instantTooltips, popovers, menús desplegables
releaseLiberación de arrastre: sensación física natural

Cuándo deshabilitar la animación por completo

Deshabilitar (hacer que shouldAnimate() devuelva false) cuando:

  • prefersReduced es true
  • isLowEnd es true y la animación no es esencial
  • El elemento está fuera de pantalla y nunca entrará en el viewport
  • La animación es puramente decorativa sin propósito de UX

Conceptos centrales

Sistema de tokens

// 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 },
}

Indicadores de tiempo de ejecución

// 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
  },
}

Accesibilidad

Orden de prioridad (de mayor a menor):

  1. prefers-reduced-motion: reduce: deshabilita todas las transformaciones, limita las transiciones de opacidad a ≤ 0.2 s
  2. Detección de dispositivos de gama baja: reduce la duración, elimina animaciones no esenciales
  3. Preferencia de diseño: todo lo demás

El movimiento debe degradarse gradualmente. Nunca debe desaparecer abruptamente de una manera que cause cambios de layout o desoriente al usuario.

// 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>

Seguridad SSR / hidratación

Regla: initial siempre debe coincidir con lo que renderiza el servidor.

// INCORRECTO: el servidor renderiza opacity:1 pero initial dice 0 → error de hidratación
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} />

// CORRECTO: usar AnimatePresence o diferir al montaje del cliente
"use client"
const [mounted, setMounted] = useState(false)
useEffect(() => setMounted(true), [])

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

Ejemplos de código

Completo: tokens + resortes + accesibilidad + protección 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) {
  // Protección SSR: inicial debe coincidir con la salida del servidor (opacity: 1)
  const [mounted, setMounted] = useState(false)
  useEffect(() => setMounted(true), [])

  // Accesibilidad: deshabilita transform cuando se prefiere movimiento reducido
  const safeMotion = useSafeMotion(motionTokens.distance.md)

  // Puerta de dispositivo: omitir animación en hardware de gama baja
  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>
  )
}

Restricciones / No objetivos

Esta habilidad no cubre:

  • Patrones de componentes de UI (botón, modal, escalonado) → ver motion-patterns
  • Arrastre, gestos, SVG, animaciones de texto, hooks personalizados → ver motion-advanced
  • Animaciones solo CSS o clases animate-* de Tailwind sin motion/react
  • Bibliotecas de animación de terceros (GSAP, anime.js, etc.)
  • Decisiones de diseño de movimiento (cuándo animar, qué enfatizar) — eso es una preocupación de diseño, no una restricción de código

Anti-patrones

Anti-patrónRegla violadaCorrección
import { motion } from "framer-motion"Regla 1Usar motion/react
initial={{ opacity: 0 }} en componente SSRRegla 2Agregar guardia de montaje
Omitir la verificación useReducedMotionRegla 3Usar hook useSafeMotion
animate={{ width: "100%" }}Regla 4Usar transformación scaleX en su lugar
transition={{ duration: 0.4 }} inlineRegla 5Usar motionTokens.duration.normal
{ stiffness: 300, damping: 30 } inlineRegla 6Usar springs.snappy
Falta la directiva "use client"Regla 7Agregar al inicio del archivo
navigator.hardwareConcurrency a nivel de móduloRegla 8Envolver en typeof navigator !== "undefined"

Habilidades relacionadas

  • motion-patterns: consume los tokens y resortes definidos aquí para construir patrones de botón, modal, escalonado, transición de página y desplazamiento. No redefine ningún valor.
  • motion-advanced: consume los tokens y resortes definidos aquí para patrones de arrastre, SVG, texto y gestos. Agrega secuencias useAnimate y hooks personalizados sobre esta base.

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 relacionados