npx skills add ...
npx skills add c-jeril/framer-motion-skills --skill framer-motion-gestures
Official Framer Motion skill for gesture animations — drag, pan, tap, hover, focus, touch animations. Use when building interactive elements with drag, pan, tap, hover, or touch gestures, or when asking about Framer Motion drag constraints, gesture handlers, or interactive animations.
npx skills add c-jeril/framer-motion-skills --skill framer-motion-gestures
Apply when implementing gesture-driven animations: drag, pan, tap, hover, focus, or touch interactions. When the user asks about drag-and-drop, interactive elements, or gesture-based UI in Framer Motion.
Related skills: For core animation use framer-motion-core; for variants use framer-motion-variants; for layout animations use framer-motion-layout.
Enable dragging with the drag prop:
| Prop | Type | Description |
|---|---|---|
| drag | bool | "x" | "y" | Enable drag on axis |
| dragConstraints | object | RefObject | Movement constraints |
| dragMomentum | boolean | Continue momentum after release (default: true) |
| dragElastic | number | object | Elasticity of bounds (default: 0) |
| dragTransition | Transition | Spring config for momentum |
| whileDrag | MotionProps | Animation while dragging |
| onDrag | function | Callback during drag |
| onDragStart | function | Callback when drag starts |
| onDragEnd | function | Callback when drag ends |
Pan is similar to drag but for pointer/touch:
Animation when pressed:
Animation on hover:
Animation when focused (keyboard):
Callbacks receive PointInfo and DragInfo:
drag without dragConstraints if the element should stay within bounds.dragElastic — it can cause visual glitches.https://www.framer.com/motion/gestures/ https://www.framer.com/motion/drag/
<motion.div
drag
dragConstraints={{
left: -100,
right: 100,
top: -50,
bottom: 50
}}
/>function Draggable() {
const constraintsRef = useRef(null);
return (
<>
<motion.div
ref={constraintsRef}
style={{
width: 500,
height: 500,
backgroundColor: "#eee"
}}
/>
<motion.div
drag
dragConstraints={constraintsRef}
/>
</>
);
}<motion.div
drag="x"
onDrag={(e, info) => {
console.log("Position:", info.point);
console.log("Velocity:", info.velocity);
}}
/><motion.button
whileTap={{ scale: 0.95, opacity: 0.8 }}
whileHover={{ scale: 1.05 }}
>
Click me
</motion.button><motion.div
whileHover={{ scale: 1.1, backgroundColor: "#ff0000" }}
style={{ width: 100, height: 100, backgroundColor: "#00ff00" }}
/><motion.div
onHoverStart={() => console.log("Hover started")}
onHoverEnd={() => console.log("Hover ended")}
/><motion.input
whileFocus={{ scale: 1.05, borderColor: "#00ff00" }}
style={{ borderWidth: 2 }}
/><motion.div
drag="x"
dragConstraints={{ left: -200, right: 200 }}
dragTransition={{
type: "spring",
stiffness: 300,
damping: 20,
mass: 1
}}
/>function DraggableBox() {
const constraintsRef = useRef(null);
return (
<>
<motion.div
ref={constraintsRef}
style={{
width: 500,
height: 500,
backgroundColor: "#f0f0f0"
}}
/>
{[1, 2, 3].map(i => (
<motion.div
key={i}
drag
dragConstraints={constraintsRef}
dragMomentum={false}
whileDrag={{ scale: 1.1 }}
/>
))}
</>
);
}function Swipeable() {
const x = useMotionValue(0);
const { scrollYProgress } = useScroll();
const opacity = useTransform(x, [-100, 0, 100], [0, 1, 0]);
return (
<motion.div
style={{ x, opacity }}
drag="x"
dragConstraints={{ left: 0, right: 0 }}
dragElastic={1}
/>
);
}onDrag={(e, info) => {
info.point // { x, y } position
info.velocity // { x, y } velocity
info.offset // { x, y } offset from start
}}