Claude Agent Skill · by Daffy0208

Animation Designer

Install Animation Designer skill for Claude Code from daffy0208/ai-dev-standards.

animationframer-motioncss-animationstransitionsmotion-design
Install
Terminal · npx
$npx skills add https://github.com/daffy0208/ai-dev-standards --skill animation-designer
Works with Paperclip

How Animation Designer fits into a Paperclip company.

Animation Designer drops into any Paperclip agent that handles animation and framer-motion work. Assign it to a specialist inside a pre-configured PaperclipOrg company and the skill becomes available on every heartbeat — no prompt engineering, no tool wiring.

S
SaaS FactoryPaired

Pre-configured AI company — 18 agents, 18 skills, one-time purchase.

$27$59
Explore pack
Source file
SKILL.md688 lines
Expand
---name: animation-designerdescription: Expert in web animations, transitions, and motion design using Framer Motion and CSSversion: 1.0.0tags: [animation, framer-motion, css-animations, transitions, motion-design]--- # Animation Designer Skill I help you create smooth, professional animations for web applications using Framer Motion and CSS. ## What I Do **UI Animations:** - Page transitions- Component enter/exit animations- Hover effects, button interactions- Loading animations **Scroll Animations:** - Parallax effects- Scroll-triggered animations- Progress indicators **Micro-interactions:** - Button press feedback- Form field focus states- Success/error animations- Drag and drop feedback ## Framer Motion Basics ### Installation ```bashnpm install framer-motion``` ### Basic Animation ```typescriptimport { motion } from 'framer-motion' export function FadeIn({ children }: { children: React.ReactNode }) {  return (    <motion.div      initial={{ opacity: 0 }}      animate={{ opacity: 1 }}      transition={{ duration: 0.5 }}    >      {children}    </motion.div>  )}``` --- ## Common Animation Patterns ### Pattern 1: Fade In on Mount ```typescriptimport { motion } from 'framer-motion' export function Card({ children }: { children: React.ReactNode }) {  return (    <motion.div      initial={{ opacity: 0, y: 20 }}      animate={{ opacity: 1, y: 0 }}      transition={{ duration: 0.4, ease: 'easeOut' }}      className="p-6 bg-white rounded-lg shadow"    >      {children}    </motion.div>  )}``` --- ### Pattern 2: Staggered List Animation ```typescriptimport { motion } from 'framer-motion' const container = {  hidden: { opacity: 0 },  show: {    opacity: 1,    transition: {      staggerChildren: 0.1    }  }} const item = {  hidden: { opacity: 0, y: 20 },  show: { opacity: 1, y: 0 }} export function List({ items }: { items: string[] }) {  return (    <motion.ul      variants={container}      initial="hidden"      animate="show"    >      {items.map((text, i) => (        <motion.li key={i} variants={item}>          {text}        </motion.li>      ))}    </motion.ul>  )}``` --- ### Pattern 3: Button Hover Animation ```typescriptimport { motion } from 'framer-motion' export function AnimatedButton({ children, onClick }: {  children: React.ReactNode  onClick: () => void}) {  return (    <motion.button      onClick={onClick}      whileHover={{ scale: 1.05 }}      whileTap={{ scale: 0.95 }}      transition={{ type: 'spring', stiffness: 400, damping: 17 }}      className="px-6 py-3 bg-blue-600 text-white rounded-lg"    >      {children}    </motion.button>  )}``` --- ### Pattern 4: Modal / Dialog Animation ```typescriptimport { motion, AnimatePresence } from 'framer-motion' export function Modal({ isOpen, onClose, children }: {  isOpen: boolean  onClose: () => void  children: React.ReactNode}) {  return (    <AnimatePresence>      {isOpen && (        <>          {/* Backdrop */}          <motion.div            initial={{ opacity: 0 }}            animate={{ opacity: 1 }}            exit={{ opacity: 0 }}            onClick={onClose}            className="fixed inset-0 bg-black/50 z-40"          />           {/* Modal */}          <motion.div            initial={{ opacity: 0, scale: 0.9, y: 20 }}            animate={{ opacity: 1, scale: 1, y: 0 }}            exit={{ opacity: 0, scale: 0.9, y: 20 }}            transition={{ type: 'spring', damping: 25, stiffness: 300 }}            className="fixed inset-0 flex items-center justify-center z-50 p-4"          >            <div className="bg-white rounded-lg p-6 max-w-md w-full">              {children}            </div>          </motion.div>        </>      )}    </AnimatePresence>  )}``` --- ### Pattern 5: Page Transition ```typescript'use client'import { motion } from 'framer-motion'import { usePathname } from 'next/navigation' export function PageTransition({ children }: { children: React.ReactNode }) {  const pathname = usePathname()   return (    <motion.div      key={pathname}      initial={{ opacity: 0, x: 20 }}      animate={{ opacity: 1, x: 0 }}      exit={{ opacity: 0, x: -20 }}      transition={{ duration: 0.3 }}    >      {children}    </motion.div>  )} // Usage in layoutexport default function Layout({ children }) {  return (    <PageTransition>      {children}    </PageTransition>  )}``` --- ## Scroll Animations ### Scroll-Triggered Animation ```typescriptimport { motion, useScroll, useTransform } from 'framer-motion'import { useRef } from 'react' export function ScrollReveal({ children }: { children: React.ReactNode }) {  const ref = useRef(null)  const { scrollYProgress } = useScroll({    target: ref,    offset: ['start end', 'end start']  })   const opacity = useTransform(scrollYProgress, [0, 0.3, 0.7, 1], [0, 1, 1, 0])  const y = useTransform(scrollYProgress, [0, 0.3, 0.7, 1], [100, 0, 0, -100])   return (    <motion.div      ref={ref}      style={{ opacity, y }}    >      {children}    </motion.div>  )}``` ### Parallax Effect ```typescriptimport { motion, useScroll, useTransform } from 'framer-motion' export function ParallaxSection() {  const { scrollY } = useScroll()  const y = useTransform(scrollY, [0, 500], [0, 150])   return (    <div className="relative h-screen overflow-hidden">      <motion.div        style={{ y }}        className="absolute inset-0"      >        <img src="/background.jpg" alt="" className="w-full h-full object-cover" />      </motion.div>       <div className="relative z-10 flex items-center justify-center h-full">        <h1 className="text-6xl font-bold text-white">          Parallax Effect        </h1>      </div>    </div>  )}``` ### Scroll Progress Indicator ```typescriptimport { motion, useScroll } from 'framer-motion' export function ScrollProgress() {  const { scrollYProgress } = useScroll()   return (    <motion.div      style={{ scaleX: scrollYProgress }}      className="fixed top-0 left-0 right-0 h-1 bg-blue-600 origin-left z-50"    />  )}``` --- ## Loading Animations ### Spinner ```typescriptimport { motion } from 'framer-motion' export function Spinner() {  return (    <motion.div      animate={{ rotate: 360 }}      transition={{        duration: 1,        repeat: Infinity,        ease: 'linear'      }}      className="w-8 h-8 border-4 border-blue-600 border-t-transparent rounded-full"    />  )}``` ### Skeleton Loader ```typescriptimport { motion } from 'framer-motion' export function SkeletonLoader() {  return (    <motion.div      animate={{ opacity: [0.5, 1, 0.5] }}      transition={{        duration: 1.5,        repeat: Infinity,        ease: 'easeInOut'      }}      className="bg-gray-200 rounded h-4 w-full"    />  )}``` ### Pulsing Dots ```typescriptimport { motion } from 'framer-motion' const dotVariants = {  start: { scale: 0.8, opacity: 0.5 },  end: { scale: 1.2, opacity: 1 }} export function PulsingDots() {  return (    <div className="flex gap-2">      {[0, 1, 2].map((i) => (        <motion.div          key={i}          variants={dotVariants}          animate="end"          initial="start"          transition={{            duration: 0.6,            repeat: Infinity,            repeatType: 'reverse',            delay: i * 0.2          }}          className="w-3 h-3 bg-blue-600 rounded-full"        />      ))}    </div>  )}``` --- ## CSS Animations ### Keyframe Animations ```css/* Fade in animation */@keyframes fadeIn {  from {    opacity: 0;    transform: translateY(20px);  }  to {    opacity: 1;    transform: translateY(0);  }} .fade-in {  animation: fadeIn 0.5s ease-out;} /* Slide in from right */@keyframes slideInRight {  from {    transform: translateX(100%);  }  to {    transform: translateX(0);  }} .slide-in-right {  animation: slideInRight 0.3s ease-out;} /* Bounce */@keyframes bounce {  0%,  100% {    transform: translateY(0);  }  50% {    transform: translateY(-10px);  }} .bounce {  animation: bounce 0.5s ease-in-out infinite;}``` ### Tailwind Animations ```typescript// tailwind.config.jsmodule.exports = {  theme: {    extend: {      keyframes: {        'fade-in': {          '0%': { opacity: '0', transform: 'translateY(10px)' },          '100%': { opacity: '1', transform: 'translateY(0)' }        },        'slide-in': {          '0%': { transform: 'translateX(-100%)' },          '100%': { transform: 'translateX(0)' }        }      },      animation: {        'fade-in': 'fade-in 0.5s ease-out',        'slide-in': 'slide-in 0.3s ease-out'      }    }  }}``` **Usage:** ```typescript<div className="animate-fade-in">Fades in</div><div className="animate-slide-in">Slides in</div>``` --- ## Micro-Interactions ### Success Checkmark Animation ```typescriptimport { motion } from 'framer-motion' export function SuccessCheckmark() {  return (    <motion.svg      width="48"      height="48"      viewBox="0 0 48 48"      initial={{ scale: 0 }}      animate={{ scale: 1 }}      transition={{ type: 'spring', stiffness: 300, damping: 20 }}    >      <motion.circle        cx="24"        cy="24"        r="22"        fill="none"        stroke="#10B981"        strokeWidth="4"        initial={{ pathLength: 0 }}        animate={{ pathLength: 1 }}        transition={{ duration: 0.5 }}      />      <motion.path        d="M12 24 L20 32 L36 16"        fill="none"        stroke="#10B981"        strokeWidth="4"        strokeLinecap="round"        strokeLinejoin="round"        initial={{ pathLength: 0 }}        animate={{ pathLength: 1 }}        transition={{ duration: 0.3, delay: 0.3 }}      />    </motion.svg>  )}``` ### Notification Badge ```typescriptimport { motion } from 'framer-motion' export function NotificationBadge({ count }: { count: number }) {  return (    <div className="relative">      <button className="p-2">        <BellIcon />      </button>       {count > 0 && (        <motion.div          initial={{ scale: 0 }}          animate={{ scale: 1 }}          transition={{ type: 'spring', stiffness: 500, damping: 15 }}          className="absolute -top-1 -right-1 bg-red-600 text-white text-xs rounded-full w-5 h-5 flex items-center justify-center"        >          {count}        </motion.div>      )}    </div>  )}``` --- ## Animation Best Practices ### 1. Performance ```typescript// ✅ Good: Animate transform and opacity (GPU accelerated)<motion.div  animate={{ x: 100, opacity: 0.5 }}/> // ❌ Bad: Animate width, height (triggers layout)<motion.div  animate={{ width: '100%', height: '200px' }}/>``` ### 2. Duration ```typescript// Too fast: < 100ms (feels abrupt)// Too slow: > 500ms (feels sluggish) // ✅ Sweet spot: 200-400ms for most UI animations<motion.div  animate={{ opacity: 1 }}  transition={{ duration: 0.3 }}/>``` ### 3. Easing ```typescript// Natural motion: easeOut (starts fast, ends slow)<motion.div  animate={{ y: 0 }}  transition={{ ease: 'easeOut' }}/> // Bouncy: spring<motion.button  whileTap={{ scale: 0.95 }}  transition={{ type: 'spring', stiffness: 400 }}/>``` ### 4. Reduce Motion (Accessibility) ```typescriptimport { useReducedMotion } from 'framer-motion' export function AccessibleAnimation({ children }: { children: React.ReactNode }) {  const shouldReduceMotion = useReducedMotion()   return (    <motion.div      initial={{ opacity: 0, y: shouldReduceMotion ? 0 : 20 }}      animate={{ opacity: 1, y: 0 }}      transition={{        duration: shouldReduceMotion ? 0 : 0.4      }}    >      {children}    </motion.div>  )}``` --- ## Complex Animations ### Drag and Drop ```typescriptimport { motion } from 'framer-motion'import { useState } from 'react' export function Draggable() {  const [position, setPosition] = useState({ x: 0, y: 0 })   return (    <motion.div      drag      dragConstraints={{ left: 0, right: 300, top: 0, bottom: 300 }}      dragElastic={0.1}      onDragEnd={(e, info) => {        setPosition({ x: info.point.x, y: info.point.y })      }}      className="w-24 h-24 bg-blue-600 rounded-lg cursor-grab active:cursor-grabbing"    />  )}``` ### Animated Number Counter ```typescriptimport { motion, useSpring, useTransform } from 'framer-motion'import { useEffect } from 'react' export function AnimatedNumber({ value }: { value: number }) {  const spring = useSpring(0, { stiffness: 100, damping: 30 })  const display = useTransform(spring, (current) =>    Math.round(current).toLocaleString()  )   useEffect(() => {    spring.set(value)  }, [spring, value])   return <motion.span>{display}</motion.span>} // Usage<AnimatedNumber value={1250} />``` --- ## When to Use Me **Perfect for:** - Creating polished UI animations- Building interactive components- Adding scroll effects- Designing loading states- Improving user feedback **I'll help you:** - Choose the right animation type- Implement smooth transitions- Optimize animation performance- Ensure accessibility- Create delightful micro-interactions ## What I'll Create ```✨ Page Transitions🎯 Micro-Interactions📜 Scroll Animations⏳ Loading States🎨 Hover Effects🎪 Complex Animations``` Let's make your interfaces feel alive!