smithery.ai115 installs
framer-motion
Framer Motion animations - motion components, variants, gestures, layout animations. Use when adding UI animations, transitions, or interactive motion effects.
How do I install this agent skill?
npx skills add https://smithery.ai --skill framer-motionIs this agent skill safe to install?
No partner audit is available yet. Read the source before installing.
What does this agent skill do?
Framer Motion
Basic Animation
import { motion } from 'framer-motion'
function AnimatedBox() {
return (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
>
Hello World
</motion.div>
)
}
Animate Properties
<motion.div
animate={{
x: 100,
y: 50,
scale: 1.2,
rotate: 180,
opacity: 0.5,
backgroundColor: '#ff0000',
borderRadius: '50%',
}}
transition={{
duration: 0.5,
ease: 'easeInOut',
delay: 0.2,
}}
/>
Transition Types
// Spring (default)
transition={{ type: 'spring', stiffness: 100, damping: 10 }}
// Tween
transition={{ type: 'tween', duration: 0.5, ease: 'easeInOut' }}
// Inertia
transition={{ type: 'inertia', velocity: 50 }}
// Ease presets
ease: 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | 'circIn' | 'circOut' | 'backIn' | 'backOut' | 'anticipate'
Variants
const containerVariants = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: {
staggerChildren: 0.1,
},
},
}
const itemVariants = {
hidden: { opacity: 0, y: 20 },
visible: { opacity: 1, y: 0 },
}
function List({ items }) {
return (
<motion.ul
variants={containerVariants}
initial="hidden"
animate="visible"
>
{items.map((item) => (
<motion.li key={item.id} variants={itemVariants}>
{item.name}
</motion.li>
))}
</motion.ul>
)
}
Hover, Tap, Focus
<motion.button
whileHover={{ scale: 1.05, backgroundColor: '#3b82f6' }}
whileTap={{ scale: 0.95 }}
whileFocus={{ boxShadow: '0 0 0 3px rgba(59, 130, 246, 0.5)' }}
>
Click me
</motion.button>
Drag
<motion.div
drag // Enable both axes
drag="x" // Horizontal only
dragConstraints={{ left: -100, right: 100, top: -50, bottom: 50 }}
dragElastic={0.2} // Elasticity outside constraints
dragMomentum={true} // Continue after release
onDragStart={(e, info) => console.log(info.point)}
onDrag={(e, info) => console.log(info.delta)}
onDragEnd={(e, info) => console.log(info.velocity)}
/>
Scroll Animations
import { motion, useScroll, useTransform } from 'framer-motion'
function ParallaxSection() {
const { scrollYProgress } = useScroll()
const y = useTransform(scrollYProgress, [0, 1], [0, -200])
const opacity = useTransform(scrollYProgress, [0, 0.5, 1], [1, 0.5, 0])
return (
<motion.div style={{ y, opacity }}>
Parallax Content
</motion.div>
)
}
// Scroll-triggered animation
function ScrollTriggered() {
return (
<motion.div
initial={{ opacity: 0, y: 50 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: '-100px' }}
transition={{ duration: 0.6 }}
>
Appears on scroll
</motion.div>
)
}
Layout Animations
function LayoutExample() {
const [isExpanded, setIsExpanded] = useState(false)
return (
<motion.div
layout
onClick={() => setIsExpanded(!isExpanded)}
style={{
width: isExpanded ? 300 : 100,
height: isExpanded ? 200 : 100,
}}
transition={{ layout: { duration: 0.3 } }}
/>
)
}
// Shared layout
import { LayoutGroup } from 'framer-motion'
function Tabs() {
const [selected, setSelected] = useState(0)
return (
<LayoutGroup>
{tabs.map((tab, i) => (
<button key={tab} onClick={() => setSelected(i)}>
{tab}
{selected === i && (
<motion.div layoutId="underline" className="underline" />
)}
</button>
))}
</LayoutGroup>
)
}
AnimatePresence (Exit Animations)
import { AnimatePresence, motion } from 'framer-motion'
function Modal({ isOpen, onClose }) {
return (
<AnimatePresence>
{isOpen && (
<motion.div
initial={{ opacity: 0, scale: 0.9 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.9 }}
transition={{ duration: 0.2 }}
>
<ModalContent onClose={onClose} />
</motion.div>
)}
</AnimatePresence>
)
}
useAnimate Hook
import { useAnimate } from 'framer-motion'
function SequenceAnimation() {
const [scope, animate] = useAnimate()
const handleClick = async () => {
await animate(scope.current, { scale: 1.2 })
await animate(scope.current, { rotate: 180 })
await animate(scope.current, { scale: 1, rotate: 0 })
}
return (
<motion.div ref={scope} onClick={handleClick}>
Click for sequence
</motion.div>
)
}
Motion Values
import { motion, useMotionValue, useTransform } from 'framer-motion'
function MotionValueExample() {
const x = useMotionValue(0)
const opacity = useTransform(x, [-200, 0, 200], [0, 1, 0])
const background = useTransform(
x,
[-200, 0, 200],
['#ff0000', '#00ff00', '#0000ff']
)
return (
<motion.div
drag="x"
style={{ x, opacity, background }}
/>
)
}
Stagger Children
const container = {
hidden: { opacity: 0 },
show: {
opacity: 1,
transition: {
staggerChildren: 0.1,
delayChildren: 0.3,
},
},
}
const item = {
hidden: { opacity: 0, y: 20 },
show: { opacity: 1, y: 0 },
}
<motion.ul variants={container} initial="hidden" animate="show">
{items.map((i) => (
<motion.li key={i} variants={item} />
))}
</motion.ul>
Loading Skeleton
function Skeleton() {
return (
<motion.div
animate={{ opacity: [0.5, 1, 0.5] }}
transition={{ duration: 1.5, repeat: Infinity }}
className="bg-gray-200 rounded h-4"
/>
)
}
Number Counter
import { motion, useSpring, useTransform } from 'framer-motion'
function Counter({ value }) {
const spring = useSpring(0, { stiffness: 100, damping: 30 })
const display = useTransform(spring, (v) => Math.round(v))
useEffect(() => {
spring.set(value)
}, [value, spring])
return <motion.span>{display}</motion.span>
}
How can the creator link this skill?
Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.
<a href="https://skillzs.dev/skills/smithery.ai/framer-motion">View framer-motion on skillZs</a>