ワンクリックで
animation-designer
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Expert in Three.js, 3D graphics, and interactive 3D visualizations
Implement accessibility (a11y) best practices to make applications usable by everyone. Use when building UIs, conducting accessibility audits, or ensuring WCAG compliance. Covers screen readers, keyboard navigation, ARIA attributes, and inclusive design patterns.
Design REST and GraphQL APIs. Use when creating backend APIs, defining API contracts, or integrating third-party services. Covers endpoint design, authentication, versioning, documentation, and best practices.
Build reliable third-party API integrations including OAuth, webhooks, rate limiting, error handling, and data sync. Use when integrating with external services (Slack, Stripe, Gmail, etc.), building API connections, handling webhooks, or implementing OAuth flows.
Master Archon MCP for strategic project management, task tracking, and knowledge base operations. The strategic layer (WHAT/WHEN) that coordinates with Skills (HOW). Use when managing projects, tracking tasks, querying knowledge bases, or implementing the Archon+Skills two-layer architecture.
Organize design assets, optimize images and fonts, maintain brand asset libraries, implement version control for assets, and enforce naming conventions. Keep design assets organized and production-ready.
| name | animation-designer |
| description | Expert in web animations, transitions, and motion design using Framer Motion and CSS |
| version | 1.0.0 |
| tags | ["animation","framer-motion","css-animations","transitions","motion-design"] |
I help you create smooth, professional animations for web applications using Framer Motion and CSS.
UI Animations:
Scroll Animations:
Micro-interactions:
npm install framer-motion
import { 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>
)
}
import { 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>
)
}
import { 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>
)
}
import { 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>
)
}
import { 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>
)
}
'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 layout
export default function Layout({ children }) {
return (
<PageTransition>
{children}
</PageTransition>
)
}
import { 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>
)
}
import { 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>
)
}
import { 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"
/>
)
}
import { 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"
/>
)
}
import { 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"
/>
)
}
import { 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>
)
}
/* 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.config.js
module.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:
<div className="animate-fade-in">Fades in</div>
<div className="animate-slide-in">Slides in</div>
import { 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>
)
}
import { 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>
)
}
// ✅ 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' }}
/>
// 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 }}
/>
// 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 }}
/>
import { 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>
)
}
import { 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"
/>
)
}
import { 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} />
Perfect for:
I'll help you:
✨ Page Transitions
🎯 Micro-Interactions
📜 Scroll Animations
⏳ Loading States
🎨 Hover Effects
🎪 Complex Animations
Let's make your interfaces feel alive!