# Animation Patterns

> Framer Motion patterns, page transitions, skeleton loading, scroll-linked animations, and gesture-based interactions for React.

- **Type:** Skill
- **Install:** `agentstack add skill-vibeeval-vibecosystem-animation-patterns`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [vibeeval](https://agentstack.voostack.com/s/vibeeval)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [vibeeval](https://github.com/vibeeval)
- **Source:** https://github.com/vibeeval/vibecosystem/tree/main/skills/animation-patterns

## Install

```sh
agentstack add skill-vibeeval-vibecosystem-animation-patterns
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Animation Patterns

Framer Motion patterns for production-quality React animations.

## Framer Motion Basics (motion components, variants)

```typescript
// Install: npm install framer-motion

import { motion } from 'framer-motion'

// Basic motion component

// Variants — define states, animate by name
const cardVariants = {
  hidden: { opacity: 0, y: 20, scale: 0.98 },
  visible: {
    opacity: 1,
    y: 0,
    scale: 1,
    transition: { duration: 0.25, ease: [0.16, 1, 0.3, 1] },
  },
  hover: {
    y: -4,
    boxShadow: '0 12px 24px -4px rgb(0 0 0 / 0.15)',
    transition: { duration: 0.2 },
  },
}

function Card({ children }: { children: React.ReactNode }) {
  return (
    
      {children}
    
  )
}
```

## Page Transitions with AnimatePresence

```typescript
import { AnimatePresence, motion } from 'framer-motion'
import { usePathname } from 'next/navigation'

const pageVariants = {
  initial: { opacity: 0, x: -8 },
  enter:   { opacity: 1, x: 0, transition: { duration: 0.2, ease: 'easeOut' } },
  exit:    { opacity: 0, x: 8,  transition: { duration: 0.15, ease: 'easeIn' } },
}

// app/layout.tsx (Next.js App Router)
export default function RootLayout({ children }: { children: React.ReactNode }) {
  const pathname = usePathname()

  return (
    
      
        
          
            {children}
          
        
      
    
  )
}

// Modal transitions — mount/unmount
function Modal({ isOpen, onClose, children }: ModalProps) {
  return (
    
      {isOpen && (
        <>
          
          
            {children}
          
        
      )}
    
  )
}
```

## Layout Animations (Shared Layout, Layout ID)

```typescript
import { motion, LayoutGroup } from 'framer-motion'
import { useState } from 'react'

// Tabs with animated indicator
function AnimatedTabs({ tabs }: { tabs: string[] }) {
  const [active, setActive] = useState(tabs[0])

  return (
    
      
        {tabs.map(tab => (
           setActive(tab)}
            className="relative px-4 py-2 text-sm font-medium"
          >
            {active === tab && (
              
            )}
            {tab}
          
        ))}
      
    
  )
}

// Expandable card with layout animation
function ExpandableCard({ title, body }: { title: string; body: string }) {
  const [expanded, setExpanded] = useState(false)

  return (
     setExpanded(e => !e)}
    >
      {title}
      
        {expanded && (
          
            {body}
          
        )}
      
    
  )
}
```

## Skeleton Loading Components

```typescript
// Base skeleton primitive
function Skeleton({ className }: { className?: string }) {
  return (
    
  )
}

// Shimmer variant (more polished)
function SkeletonShimmer({ className }: { className?: string }) {
  return (
    
      
    
  )
}

// Card skeleton
function CardSkeleton() {
  return (
    
      
        
        
          
          
        
      
      
      
      
    
  )
}
```

## Scroll-Linked Animations

```typescript
import { useScroll, useTransform, motion } from 'framer-motion'
import { useRef } from 'react'

// Parallax hero
function ParallaxHero() {
  const ref = useRef(null)
  const { scrollYProgress } = useScroll({ target: ref, offset: ['start start', 'end start'] })

  const y = useTransform(scrollYProgress, [0, 1], ['0%', '50%'])
  const opacity = useTransform(scrollYProgress, [0, 0.5], [1, 0])

  return (
    
      
        
      
      
        Hero Title
      
    
  )
}

// Fade-in on scroll (section reveal)
function FadeInSection({ children }: { children: React.ReactNode }) {
  const ref = useRef(null)
  const { scrollYProgress } = useScroll({ target: ref, offset: ['start 0.9', 'start 0.6'] })
  const opacity = useTransform(scrollYProgress, [0, 1], [0, 1])
  const y = useTransform(scrollYProgress, [0, 1], [24, 0])

  return (
    
      {children}
    
  )
}
```

## Staggered Children Animations

```typescript
const listVariants = {
  hidden: {},
  visible: {
    transition: {
      staggerChildren: 0.06,     // 60ms between each child
      delayChildren: 0.1,
    },
  },
}

const itemVariants = {
  hidden:  { opacity: 0, x: -12 },
  visible: { opacity: 1, x: 0, transition: { duration: 0.25, ease: 'easeOut' } },
}

function AnimatedList({ items }: { items: string[] }) {
  return (
    
      {items.map(item => (
        
          {item}
        
      ))}
    
  )
}
```

## Gesture Interactions (Drag, Tap, Hover)

```typescript
import { motion, useDragControls } from 'framer-motion'

// Draggable card
function DraggableCard() {
  return (
    
      Drag me
    
  )
}

// Bottom sheet (drag to dismiss)
function BottomSheet({ onClose }: { onClose: () => void }) {
  return (
     {
        if (info.offset.y > 100) onClose()
      }}
      initial={{ y: '100%' }}
      animate={{ y: 0 }}
      exit={{ y: '100%' }}
      transition={{ type: 'spring', damping: 30, stiffness: 300 }}
      className="fixed bottom-0 inset-x-0 rounded-t-2xl bg-white p-6 shadow-lg"
    >
      
      {/* content */}
    
  )
}

// Press / tap feedback
function PressButton({ children, onClick }: ButtonProps) {
  return (
    
      {children}
    
  )
}
```

## Reduced Motion Respect

```typescript
import { useReducedMotion, motion } from 'framer-motion'

// Hook-based — apply conditionally
function FadeIn({ children }: { children: React.ReactNode }) {
  const prefersReducedMotion = useReducedMotion()

  return (
    
      {children}
    
  )
}

// Global — wrap app with MotionConfig
import { MotionConfig } from 'framer-motion'

export function Providers({ children }: { children: React.ReactNode }) {
  const prefersReducedMotion = useReducedMotion()
  return (
    
      {children}
    
  )
}

// CSS fallback (always include alongside JS animations)
// @media (prefers-reduced-motion: reduce) { .animated { animation: none !important; } }
```

## Performance Tips

```typescript
// 1. Use transform properties — GPU accelerated
// GOOD: x, y, scale, rotate, opacity (compositor layer)
// BAD: width, height, top, left, margin (layout thrash)

// 2. will-change for known animations (use sparingly)

// 3. layout prop only when needed — triggers LayoutAnimation (expensive)
          // layout: expensive, triggers every render
 // layout="position": cheaper, only position

// 4. LazyMotion — reduces bundle size (removes unused features)
import { LazyMotion, domAnimation, m } from 'framer-motion'

  {/* load only DOM animations */}
    {/* use m instead of motion */}

// 5. Avoid animating inside virtualized lists
// AnimatePresence + virtualization = bugs. Use CSS transitions for list items.

// 6. Spring physics vs duration — springs feel more natural
const spring = { type: 'spring', stiffness: 300, damping: 25 }
const duration = { duration: 0.3, ease: [0.16, 1, 0.3, 1] }
// Springs: interactive elements (drag release, hover)
// Duration: page transitions, content reveal
```

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [vibeeval](https://github.com/vibeeval)
- **Source:** [vibeeval/vibecosystem](https://github.com/vibeeval/vibecosystem)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-vibeeval-vibecosystem-animation-patterns
- Seller: https://agentstack.voostack.com/s/vibeeval
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
