Communitygithub.com

运动基础

为 React / Next.js 使用 motion/react 提供运动令牌(motion tokens)、弹簧预设(spring presets)、性能规则、设备适配、无障碍强制执行以及 SSR 安全性。这是基础层——所有其他运动技能都依赖于此。在设置运动令牌、弹簧预设、减少运动处理或 React / Next.js 中的 SSR 安全动画时使用。

运动基础 是什么?

Motion Foundations 是运动系统的基础层。它定义了所有下游技能(如 motion-patterns、motion-advanced)所继承的每个值、约束和规则。该技能提供了共享的 `motionTokens` 对象(包含持续时间、缓动、距离、缩放)、一个包含 5 个命名配置的 `springs` 预设映射、一个由所有组件使用的 `shouldAnimate()` 门控函数,以及通过 `useReducedMotion` 实现的无障碍兼容动画默认值。它还确保 SSR 安全的初始状态,无 hydration 警告。它支持多个平台,包括 React、Next.js 以及所有使用 `motion/react`(而非 `framer-motion`)的组件。主要原则是:动画必须引导注意力、传达状态或保持空间连续性;响应速度总是优先于平滑度。规则包括:仅使用 `motion/react`、`initial` 必须匹配服务器输出、减少运动覆盖所有内容、禁止动画化 `width` 和 `height` 等布局属性、禁止使用硬编码值。该技能还提供了根据令牌选择持续时间、根据预设选择弹簧以及判断何时完全禁用动画的决策指南。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/motion-foundations

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Motion Foundations

运动系统的基础层。定义了下游技能(motion-patterns、motion-advanced)继承的每个值、约束和规则。在开始任何动画工作之前加载此技能。

何时激活

  • 从零开始创建任何动画组件
  • 设置令牌、弹簧预设或缓动值
  • 实现 prefers-reduced-motion 支持
  • 调试由动画初始状态引起的 hydration 不匹配
  • 评估某个动画是否应该存在

输出

此技能产生:

  • 一个共享的 motionTokens 对象(持续时间、缓动、距离、缩放)
  • 一个共享的 springs 预设映射(5 个命名配置)
  • 所有组件使用的 shouldAnimate() 门控函数
  • 通过 useReducedMotion 实现的无障碍兼容动画默认值
  • 零 hydration 警告的 SSR 安全初始状态

原则

动画必须至少满足以下条件之一,否则必须移除:

  • 引导注意力
  • 传达状态
  • 保持空间连续性

响应速度始终优先于平滑度。导致输入延迟的 60 fps 动画比没有动画更糟糕。

规则

这些是不可谈判的。它们适用于系统中的每个组件。

  1. 仅使用 motion/react。 永远不要从 framer-motion 导入。不要在同一个树中混合使用两者。
  2. initial 必须匹配服务器输出。 如果服务器渲染 opacity: 1,则 initial 属性也必须是 opacity: 1。没有例外。
  3. 减少运动覆盖一切。 当 useReducedMotion() 返回 true 或 prefersReduced 为 true 时,所有变换都被禁用。仅允许 ≤ 0.2s 的仅透明度淡入淡出作为后备。
  4. 永远不要动画化布局属性。 width、height、top、left、margin、padding 禁止用于 animate。仅使用 transform 和 opacity。
  5. 所有令牌值来自 motionTokens。 禁止在组件文件中使用硬编码的持续时间和缓动。
  6. 所有弹簧配置来自 springs 映射。 禁止内联 stiffness/damping 值。
  7. 每个从 motion/react 导入的文件都需要 "use client"。
  8. 永远不要在模块级别读取 window 或 navigator。 始终用 typeof window !== "undefined" 进行保护。

决策指南

选择持续时间

令牌使用场景
instant工具提示显示/隐藏、焦点环、徽章更新
fast按钮反馈、图标切换、芯片切换
normal模态框打开、卡片展开、页面元素进入
slow主打内容进入、整页过渡
crawl有意的叙事;谨慎使用

选择弹簧

预设使用场景
snappy默认 UI — 按钮、芯片、导航项
gentle卡片、模态框、面板柔和着陆
bouncy有趣时刻 — 空状态、新手引导
instant工具提示、弹出框、下拉菜单
release拖拽释放 — 自然的物理感觉

何时完全禁用动画

在以下情况下禁用(使 shouldAnimate() 返回 false):

  • prefersReduced 为 true
  • isLowEnd 为 true 且动画非必需
  • 元素在屏幕外且永远不会进入视口
  • 动画纯装饰性且无 UX 目的

核心概念

令牌系统

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

运行时标志

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

无障碍

优先级顺序(从高到低):

  1. prefers-reduced-motion: reduce — 禁用所有变换,将透明度过渡限制在 ≤ 0.2s
  2. 低端设备检测 — 缩短持续时间,移除非必要动画
  3. 设计偏好 — 其他一切

运动必须优雅降级。它绝不能突然消失,导致布局偏移或混淆方向感。

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

SSR / hydration 安全性

规则:initial 必须始终匹配服务器渲染的内容。

// 错误 — 服务器渲染 opacity:1,但 initial 设为 0 → hydration 不匹配
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} />

// 正确 — 使用 AnimatePresence 或延迟到客户端挂载
"use client"
const [mounted, setMounted] = useState(false)
useEffect(() => setMounted(true), [])

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

代码示例

端到端:令牌 + 弹簧 + 无障碍 + 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) {
  // SSR 防护 — initial 必须匹配服务器输出 (opacity: 1)
  const [mounted, setMounted] = useState(false)
  useEffect(() => setMounted(true), [])

  // 无障碍 — 当偏好减少运动时禁用变换
  const safeMotion = useSafeMotion(motionTokens.distance.md)

  // 设备门控 — 在低端硬件上跳过动画
  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>
  )
}

约束 / 非目标

此技能不涵盖:

  • UI 组件模式(按钮、模态框、交错)→ 参见 motion-patterns
  • 拖拽、手势、SVG、文本动画、自定义 hooks → 参见 motion-advanced
  • 纯 CSS 动画或未使用 motion/react 的 Tailwind animate-* 类
  • 第三方动画库(GSAP、anime.js 等)
  • 动画设计决策(何时动画、强调什么)— 这是设计问题,而非代码约束

反模式

反模式违反的规则修复
import { motion } from "framer-motion"规则 1使用 motion/react
在 SSR 组件上使用 initial={{ opacity: 0 }}规则 2添加挂载防护
跳过 useReducedMotion 检查规则 3使用 useSafeMotion hook
animate={{ width: "100%" }}规则 4改用 scaleX 变换
内联 transition={{ duration: 0.4 }}规则 5使用 motionTokens.duration.normal
内联 { stiffness: 300, damping: 30 }规则 6使用 springs.snappy
缺少 "use client" 指令规则 7添加到文件顶部
在模块级别使用 navigator.hardwareConcurrency规则 8包裹在 typeof navigator !== "undefined" 中

相关技能

  • motion-patterns — 使用此处定义的令牌和弹簧来构建按钮、模态框、交错、页面过渡和滚动模式。不会重新定义任何值。
  • motion-advanced — 使用此处定义的令牌和弹簧来实现拖拽、SVG、文本和手势模式。在此基础上添加 useAnimate 序列和自定义 hooks。

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.

相关技能