motion-animation-patterns

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Motion Animation Patterns

Motion 动画模式

Overview

概述

This skill provides comprehensive guidance for implementing Motion (Framer Motion) animations in React 19 applications. It ensures consistent, performant, and accessible animations across the UI using centralized animation presets.
When to use this skill:
  • Adding page transition animations
  • Implementing modal/dialog entrance/exit animations
  • Creating staggered list animations
  • Adding hover and tap micro-interactions
  • Implementing skeleton loading states
  • Creating collapse/expand animations
  • Building toast/notification animations
Bundled Resources:
  • references/animation-presets.md
    - Complete preset API reference
  • examples/component-patterns.md
    - Common animation patterns

本技能为在React 19应用中实现Motion(Framer Motion)动画提供全面指导。通过集中式动画预设,确保UI中的动画一致、高性能且具备可访问性。
何时使用此技能:
  • 添加页面过渡动画
  • 实现模态框/对话框的进入/退出动画
  • 创建列表交错动画
  • 添加悬停和点击微交互
  • 实现骨架屏加载状态
  • 创建展开/收起动画
  • 构建提示框/通知动画
附带资源:
  • references/animation-presets.md
    - 完整的预设API参考文档
  • examples/component-patterns.md
    - 常见动画模式示例

Core Architecture

核心架构

Animation Presets Library (
frontend/src/lib/animations.ts
)

动画预设库(
frontend/src/lib/animations.ts

All animations MUST use the centralized
animations.ts
presets. This ensures:
  • Consistent motion language across the app
  • RTL-aware animations (Hebrew support)
  • Performance optimization
  • Easy maintainability
typescript
// ✅ CORRECT: Import from animations.ts
import { motion, AnimatePresence } from 'motion/react';
import { fadeIn, slideUp, staggerContainer, modalContent } from '@/lib/animations';

// ❌ WRONG: Inline animation values
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }}>

所有动画必须使用集中式的
animations.ts
预设,这能确保:
  • 应用内动画语言的一致性
  • 支持RTL(从右到左)布局的动画(适配希伯来语)
  • 性能优化
  • 易于维护
typescript
// ✅ CORRECT: Import from animations.ts
import { motion, AnimatePresence } from 'motion/react';
import { fadeIn, slideUp, staggerContainer, modalContent } from '@/lib/animations';

// ❌ WRONG: Inline animation values
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }}>

Available Presets

可用预设

Transition Timing

过渡时长

PresetDurationEaseUse For
transitions.fast
0.15seaseOutMicro-interactions
transitions.normal
0.2seaseOutMost animations
transitions.slow
0.3seaseInOutEmphasis effects
transitions.spring
spring300/25Playful elements
transitions.gentleSpring
spring200/20Modals/overlays
预设时长缓动效果适用场景
transitions.fast
0.15seaseOut微交互
transitions.normal
0.2seaseOut大多数动画
transitions.slow
0.3seaseInOut强调效果
transitions.spring
spring300/25活泼元素
transitions.gentleSpring
spring200/20模态框/浮层

Basic Animations

基础动画

PresetEffectUse For
fadeIn
Opacity fadeSimple reveal
fadeScale
Fade + slight scaleSubtle emphasis
scaleIn
Fade + scale from centerBadges, buttons
预设效果适用场景
fadeIn
透明度淡入简单的内容展示
fadeScale
淡入+轻微缩放微妙的强调效果
scaleIn
淡入+从中心缩放徽章、按钮

Slide Animations (RTL-Aware)

滑动动画(支持RTL)

PresetDirectionUse For
slideInRight
Right to centerRTL Hebrew UI (natural)
slideInLeft
Left to centerLTR content
slideUp
Bottom to centerCards, panels
slideDown
Top to centerDropdowns
预设方向适用场景
slideInRight
从右侧到中心RTL希伯来语UI(符合自然阅读方向)
slideInLeft
从左侧到中心LTR内容
slideUp
从底部到中心卡片、面板
slideDown
从顶部到中心下拉菜单

List/Stagger Animations

列表/交错动画

PresetEffectUse For
staggerContainer
Parent with staggerList wrappers
staggerContainerFast
Fast staggerQuick lists
staggerItem
Fade + slide childList items
staggerItemRight
RTL slide childHebrew lists
预设效果适用场景
staggerContainer
父容器带动画交错列表容器
staggerContainerFast
快速交错短列表
staggerItem
子元素淡入+滑动列表项
staggerItemRight
RTL方向滑动子元素希伯来语列表

Modal/Dialog Animations

模态框/对话框动画

PresetEffectUse For
modalBackdrop
Overlay fadeModal background
modalContent
Scale + fadeModal body
sheetContent
Slide from bottomMobile sheets
dropdownDown
Scale from topDropdown menus
dropdownUp
Scale from bottomContext menus
预设效果适用场景
modalBackdrop
遮罩层淡入模态框背景
modalContent
缩放+淡入模态框主体
sheetContent
从底部滑入移动端底部弹窗
dropdownDown
从顶部缩放下拉菜单
dropdownUp
从底部缩放上下文菜单

Page Transitions

页面过渡

PresetEffectUse For
pageFade
Simple fadeRoute changes
pageSlide
RTL slideNavigation
预设效果适用场景
pageFade
简单淡入淡出路由切换
pageSlide
RTL方向滑动页面导航

Micro-Interactions

微交互

PresetEffectUse For
tapScale
Scale on tapButtons, cards
hoverLift
Lift + shadowCards, list items
buttonPress
Press effectInteractive buttons
cardHover
Hover emphasisCard components
预设效果适用场景
tapScale
点击时缩放按钮、卡片
hoverLift
悬停时抬起+阴影卡片、列表项
buttonPress
按压效果交互按钮
cardHover
悬停强调卡片组件

Loading States

加载状态

PresetEffectUse For
pulse
Opacity pulseSkeleton loaders
shimmer
Sliding highlightShimmer effect
预设效果适用场景
pulse
透明度脉冲骨架屏加载器
shimmer
滑动高亮闪光效果

Utility Animations

工具类动画

PresetEffectUse For
toastSlideIn
Slide + scaleNotifications
collapse
Height animationAccordions

预设效果适用场景
toastSlideIn
滑动+缩放通知提示
collapse
高度动画折叠面板

Implementation Patterns

实现模式

1. Page Transitions

1. 页面过渡

Wrap routes with
AnimatePresence
for smooth page changes:
tsx
// frontend/src/components/AnimatedRoutes.tsx
import { Routes, Route, useLocation } from 'react-router';
import { AnimatePresence, motion } from 'motion/react';
import { pageFade } from '@/lib/animations';

export function AnimatedRoutes() {
  const location = useLocation();

  return (
    <AnimatePresence mode="wait">
      <motion.div key={location.pathname} {...pageFade} className="min-h-screen">
        <Routes location={location}>
          {/* routes */}
        </Routes>
      </motion.div>
    </AnimatePresence>
  );
}
使用
AnimatePresence
包裹路由,实现流畅的页面切换:
tsx
// frontend/src/components/AnimatedRoutes.tsx
import { Routes, Route, useLocation } from 'react-router';
import { AnimatePresence, motion } from 'motion/react';
import { pageFade } from '@/lib/animations';

export function AnimatedRoutes() {
  const location = useLocation();

  return (
    <AnimatePresence mode="wait">
      <motion.div key={location.pathname} {...pageFade} className="min-h-screen">
        <Routes location={location}>
          {/* routes */}
        </Routes>
      </motion.div>
    </AnimatePresence>
  );
}

2. Modal Animations

2. 模态框动画

Use
AnimatePresence
for enter/exit animations:
tsx
import { motion, AnimatePresence } from 'motion/react';
import { modalBackdrop, modalContent } from '@/lib/animations';

function Modal({ isOpen, onClose, children }) {
  return (
    <AnimatePresence>
      {isOpen && (
        <>
          <motion.div
            {...modalBackdrop}
            className="fixed inset-0 z-50 bg-black/50"
            onClick={onClose}
          />
          <motion.div
            {...modalContent}
            className="fixed inset-0 z-50 flex items-center justify-center p-4 pointer-events-none"
          >
            <div className="bg-white rounded-2xl p-6 pointer-events-auto">
              {children}
            </div>
          </motion.div>
        </>
      )}
    </AnimatePresence>
  );
}
使用
AnimatePresence
实现进入/退出动画:
tsx
import { motion, AnimatePresence } from 'motion/react';
import { modalBackdrop, modalContent } from '@/lib/animations';

function Modal({ isOpen, onClose, children }) {
  return (
    <AnimatePresence>
      {isOpen && (
        <>
          <motion.div
            {...modalBackdrop}
            className="fixed inset-0 z-50 bg-black/50"
            onClick={onClose}
          />
          <motion.div
            {...modalContent}
            className="fixed inset-0 z-50 flex items-center justify-center p-4 pointer-events-none"
          >
            <div className="bg-white rounded-2xl p-6 pointer-events-auto">
              {children}
            </div>
          </motion.div>
        </>
      )}
    </AnimatePresence>
  );
}

3. Staggered List Animations

3. 列表交错动画

Use parent container with child variants:
tsx
import { motion } from 'motion/react';
import { staggerContainer, staggerItem } from '@/lib/animations';

function ItemList({ items }) {
  return (
    <motion.ul
      variants={staggerContainer}
      initial="initial"
      animate="animate"
      className="space-y-2"
    >
      {items.map((item) => (
        <motion.li key={item.id} variants={staggerItem}>
          <ItemCard item={item} />
        </motion.li>
      ))}
    </motion.ul>
  );
}
使用父容器搭配子元素变体:
tsx
import { motion } from 'motion/react';
import { staggerContainer, staggerItem } from '@/lib/animations';

function ItemList({ items }) {
  return (
    <motion.ul
      variants={staggerContainer}
      initial="initial"
      animate="animate"
      className="space-y-2"
    >
      {items.map((item) => (
        <motion.li key={item.id} variants={staggerItem}>
          <ItemCard item={item} />
        </motion.li>
      ))}
    </motion.ul>
  );
}

4. Card Hover Interactions

4. 卡片悬停交互

Apply micro-interactions to cards:
tsx
import { motion } from 'motion/react';
import { cardHover, tapScale } from '@/lib/animations';

function Card({ onClick, children }) {
  return (
    <motion.div
      {...cardHover}
      {...tapScale}
      onClick={onClick}
      className="p-4 rounded-lg bg-white cursor-pointer"
    >
      {children}
    </motion.div>
  );
}
为卡片添加微交互:
tsx
import { motion } from 'motion/react';
import { cardHover, tapScale } from '@/lib/animations';

function Card({ onClick, children }) {
  return (
    <motion.div
      {...cardHover}
      {...tapScale}
      onClick={onClick}
      className="p-4 rounded-lg bg-white cursor-pointer"
    >
      {children}
    </motion.div>
  );
}

5. Skeleton Loaders with Motion

5. 基于Motion的骨架屏加载器

Use Motion pulse for consistent animation:
tsx
import { motion } from 'motion/react';
import { pulse } from '@/lib/animations';

function Skeleton({ className }) {
  return (
    <motion.div
      variants={pulse}
      initial="initial"
      animate="animate"
      className={"bg-gray-200 rounded " + className}
      aria-hidden="true"
    />
  );
}
使用Motion的脉冲动画实现一致的加载效果:
tsx
import { motion } from 'motion/react';
import { pulse } from '@/lib/animations';

function Skeleton({ className }) {
  return (
    <motion.div
      variants={pulse}
      initial="initial"
      animate="animate"
      className={"bg-gray-200 rounded " + className}
      aria-hidden="true"
    />
  );
}

6. Collapse/Expand Animations

6. 展开/收起动画

For accordions and expandable sections:
tsx
import { motion, AnimatePresence } from 'motion/react';
import { collapse } from '@/lib/animations';

function Accordion({ isExpanded, children }) {
  return (
    <AnimatePresence>
      {isExpanded && (
        <motion.div {...collapse} className="overflow-hidden">
          {children}
        </motion.div>
      )}
    </AnimatePresence>
  );
}

适用于折叠面板和可展开区域:
tsx
import { motion, AnimatePresence } from 'motion/react';
import { collapse } from '@/lib/animations';

function Accordion({ isExpanded, children }) {
  return (
    <AnimatePresence>
      {isExpanded && (
        <motion.div {...collapse} className="overflow-hidden">
          {children}
        </motion.div>
      )}
    </AnimatePresence>
  );
}

AnimatePresence Rules

AnimatePresence 使用规则

MANDATORY: Use
AnimatePresence
for exit animations:
tsx
// ✅ CORRECT: Wrap conditional renders
<AnimatePresence>
  {isVisible && (
    <motion.div {...fadeIn}>Content</motion.div>
  )}
</AnimatePresence>

// ❌ WRONG: No exit animation
{isVisible && (
  <motion.div {...fadeIn}>Content</motion.div>
)}
Mode options:
  • mode="wait"
    - Wait for exit before enter (page transitions)
  • mode="popLayout"
    - Layout animations for removing items
  • Default - Simultaneous enter/exit

强制要求:使用
AnimatePresence
实现退出动画:
tsx
// ✅ CORRECT: Wrap conditional renders
<AnimatePresence>
  {isVisible && (
    <motion.div {...fadeIn}>Content</motion.div>
  )}
</AnimatePresence>

// ❌ WRONG: No exit animation
{isVisible && (
  <motion.div {...fadeIn}>Content</motion.div>
)}
模式选项:
  • mode="wait"
    - 等待退出动画完成后再执行进入动画(适用于页面过渡)
  • mode="popLayout"
    - 移除元素时的布局动画
  • 默认 - 同时执行进入和退出动画

RTL/Hebrew Considerations

RTL/希伯来语适配注意事项

The animation presets are RTL-aware:
  • slideInRight
    - Natural entry direction for Hebrew
  • staggerItemRight
    - RTL list animations
  • pageSlide
    - Pages slide from left (correct for RTL)

动画预设已适配RTL布局:
  • slideInRight
    - 希伯来语内容的自然进入方向
  • staggerItemRight
    - RTL列表动画
  • pageSlide
    - 页面从左侧滑入(符合RTL布局逻辑)

Performance Best Practices

性能最佳实践

  1. Use preset transitions: Already optimized
  2. Avoid layout animations on large lists: Can cause jank
  3. Use
    layout
    prop sparingly
    : Only when needed
  4. Prefer opacity/transform: Hardware accelerated
  5. Don't animate width/height directly: Use
    collapse
    preset
tsx
// ✅ CORRECT: Transform-based
<motion.div {...slideUp}>

// ❌ AVOID: Layout-heavy
<motion.div animate={{ width: '100%', marginLeft: '20px' }}>

  1. 使用预设过渡效果:已完成性能优化
  2. 避免在大型列表上使用布局动画:可能导致卡顿
  3. 谨慎使用
    layout
    属性
    :仅在必要时使用
  4. 优先使用透明度/变换动画:由硬件加速
  5. 不要直接动画化宽度/高度:使用
    collapse
    预设
tsx
// ✅ CORRECT: Transform-based
<motion.div {...slideUp}>

// ❌ AVOID: Layout-heavy
<motion.div animate={{ width: '100%', marginLeft: '20px' }}>

Testing Animations

动画测试

Verify 60fps performance:
  1. Open Chrome DevTools > Performance tab
  2. Record while triggering animations
  3. Check for frame drops below 60fps

验证动画性能是否达到60fps:
  1. 打开Chrome开发者工具 > 性能面板
  2. 触发动画时进行录制
  3. 检查是否存在帧率低于60fps的情况

Checklist for New Components

新组件开发检查清单

When adding animations:
  • Import from
    @/lib/animations
    , not inline values
  • Use
    AnimatePresence
    for conditional renders
  • Apply appropriate preset for the interaction type
  • Test with RTL locale (Hebrew)
  • Verify 60fps performance
  • Ensure animations don't block user interaction

添加动画时需确认:
  • @/lib/animations
    导入,而非使用内联值
  • 对条件渲染的元素使用
    AnimatePresence
  • 根据交互类型选择合适的预设
  • 在RTL语言环境(希伯来语)下测试
  • 验证帧率达到60fps
  • 确保动画不会阻碍用户交互

Anti-Patterns (FORBIDDEN)

反模式(禁止使用)

tsx
// ❌ NEVER use inline animation values
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }}>

// ❌ NEVER animate without AnimatePresence for conditionals
{isOpen && <motion.div exit={{ opacity: 0 }}>}

// ❌ NEVER animate layout-heavy properties
<motion.div animate={{ width: newWidth, height: newHeight }}>

// ❌ NEVER use CSS transitions alongside Motion
<motion.div {...fadeIn} className="transition-all duration-300">

tsx
// ❌ NEVER use inline animation values
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }}>

// ❌ NEVER animate without AnimatePresence for conditionals
{isOpen && <motion.div exit={{ opacity: 0 }}>}

// ❌ NEVER animate layout-heavy properties
<motion.div animate={{ width: newWidth, height: newHeight }}>

// ❌ NEVER use CSS transitions alongside Motion
<motion.div {...fadeIn} className="transition-all duration-300">

Integration with Agents

与角色的协作

Frontend UI Developer

前端UI开发者

  • Uses animation presets for all motion effects
  • References this skill for implementation patterns
  • Ensures consistent animation language
  • 使用动画预设实现所有动效
  • 参考本技能获取实现模式
  • 确保动画语言的一致性

Rapid UI Designer

快速UI设计师

  • Specifies animation types in design specs
  • References available presets for motion design
  • 在设计规范中指定动画类型
  • 参考可用预设进行动效设计

Code Quality Reviewer

代码质量审核者

  • Checks for inline animation anti-patterns
  • Validates AnimatePresence usage
  • Ensures performance best practices

Skill Version: 1.0.0 Last Updated: 2026-01-06 Maintained by: Yonatan Gross
  • 检查是否存在内联动画的反模式
  • 验证
    AnimatePresence
    的使用是否正确
  • 确保符合性能最佳实践

技能版本:1.0.0 最后更新:2026-01-06 维护者:Yonatan Gross

Related Skills

相关技能

  • a11y-testing
    - Testing animations for reduced motion preferences and focus visibility
  • focus-management
    - Focus management during modal animations and page transitions
  • design-system-starter
    - Integrating animation presets into design system components
  • i18n-date-patterns
    - RTL-aware animations for Hebrew and Arabic layouts
  • a11y-testing
    - 针对减少动效偏好和焦点可见性测试动画
  • focus-management
    - 模态框动画和页面过渡中的焦点管理
  • design-system-starter
    - 将动画预设集成到设计系统组件中
  • i18n-date-patterns
    - 适配希伯来语和阿拉伯语布局的RTL动画

Key Decisions

关键决策

DecisionChoiceRationale
Animation LibraryMotion (Framer Motion)Declarative API, AnimatePresence, spring physics
Animation StrategyCentralized PresetsConsistency, maintainability, RTL awareness
Performance Target60fpsHardware-accelerated transforms only
Exit AnimationsAnimatePresence RequiredProper cleanup, layout stability
Transition TimingSpring-basedNatural motion, responsive feel
决策选择理由
动画库Motion(Framer Motion)声明式API、AnimatePresence支持、弹簧物理动效
动画策略集中式预设一致性、可维护性、RTL适配
性能目标60fps仅使用硬件加速的变换动画
退出动画强制使用AnimatePresence正确清理、布局稳定性
过渡时长基于弹簧动效自然的运动感、响应式体验

Capability Details

功能详情

animation-presets

animation-presets

Keywords: animation, motion, preset, fadeIn, slideUp, scaleIn Solves:
  • How do I create consistent animations?
  • What animation presets are available?
  • Where should I define animations?
关键词: animation, motion, preset, fadeIn, slideUp, scaleIn 解决问题:
  • 如何创建一致的动画?
  • 有哪些可用的动画预设?
  • 应该在哪里定义动画?

page-transitions

page-transitions

Keywords: page, transition, route, navigation, AnimatePresence Solves:
  • How do I animate page transitions?
  • Add route change animations
  • AnimatePresence for page exits
关键词: page, transition, route, navigation, AnimatePresence 解决问题:
  • 如何实现页面过渡动画?
  • 添加路由切换动画
  • 使用AnimatePresence实现页面退出动画

modal-animations

modal-animations

Keywords: modal, dialog, overlay, backdrop, entrance, exit Solves:
  • How do I animate modals?
  • Dialog entrance/exit animations
  • Backdrop fade effects
关键词: modal, dialog, overlay, backdrop, entrance, exit 解决问题:
  • 如何实现模态框动画?
  • 对话框进入/退出动画
  • 遮罩层淡入效果

stagger-animations

stagger-animations

Keywords: stagger, list, children, delay, sequence Solves:
  • How do I stagger list animations?
  • Animate children sequentially
  • List item entrance effects
关键词: stagger, list, children, delay, sequence 解决问题:
  • 如何实现列表交错动画?
  • 按顺序动画化子元素
  • 列表项进入效果

hover-interactions

hover-interactions

Keywords: hover, tap, whileHover, whileTap, micro-interaction Solves:
  • How do I add hover effects?
  • Button press animations
  • Micro-interactions for buttons
关键词: hover, tap, whileHover, whileTap, micro-interaction 解决问题:
  • 如何添加悬停效果?
  • 按钮按压动画
  • 按钮微交互

skeleton-loaders

skeleton-loaders

Keywords: skeleton, loading, pulse, placeholder, shimmer Solves:
  • How do I create skeleton loaders?
  • Animated loading placeholders
  • Pulse animation for loading states
关键词: skeleton, loading, pulse, placeholder, shimmer 解决问题:
  • 如何创建骨架屏加载器?
  • 动画化加载占位符
  • 加载状态的脉冲动画

rtl-animations

rtl-animations

Keywords: rtl, ltr, hebrew, arabic, direction, i18n Solves:
  • How do I handle RTL animations?
  • Direction-aware slide animations
  • Hebrew/Arabic animation support
关键词: rtl, ltr, hebrew, arabic, direction, i18n 解决问题:
  • 如何处理RTL布局下的动画?
  • 适配方向的滑动动画
  • 希伯来语/阿拉伯语动画支持

collapse-expand

collapse-expand

Keywords: collapse, expand, accordion, height, auto Solves:
  • How do I animate height changes?
  • Accordion expand/collapse
  • Animate to auto height
关键词: collapse, expand, accordion, height, auto 解决问题:
  • 如何实现高度变化动画?
  • 折叠面板展开/收起
  • 动画化自适应高度