A production-ready motion library for React that provides comprehensive animation and gesture APIs for creating fluid, performant interactions.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Imperative animation hooks and utilities for programmatic control over animations, including scoped animations and animation controls.
Creates a scoped animation function that can target elements within a specific scope.
/**
* Creates a scoped animation function for imperative animations
* @returns Tuple of [scope ref, animate function]
*/
function useAnimate<T extends Element = any>(): [
scope: AnimationScope<T>,
animate: (
target: string | Element,
keyframes: Record<string, any> | Record<string, any>[],
options?: AnimationOptions
) => AnimationPlaybackControls
];
interface AnimationScope<T extends Element = any> extends React.RefObject<T> {
/**
* Animation scope reference for targeting elements
*/
}
interface AnimationOptions {
/**
* Animation duration in seconds
*/
duration?: number;
/**
* Delay before animation starts in seconds
*/
delay?: number;
/**
* Easing function or array of easing functions
*/
ease?: Easing | Easing[];
/**
* Number of times to repeat animation
*/
repeat?: number;
/**
* Type of repeat: "loop" or "reverse"
*/
repeatType?: "loop" | "reverse" | "mirror";
/**
* Delay between repeats in seconds
*/
repeatDelay?: number;
/**
* Animation type
*/
type?: "tween" | "spring" | "keyframes" | "inertia";
/**
* Spring configuration (when type is "spring")
*/
bounce?: number;
damping?: number;
mass?: number;
stiffness?: number;
velocity?: number;
restSpeed?: number;
restDelta?: number;
}
interface AnimationPlaybackControls {
/**
* Stop the animation
*/
stop: () => void;
/**
* Pause the animation
*/
pause: () => void;
/**
* Resume the animation
*/
play: () => void;
/**
* Reverse the animation direction
*/
reverse: () => void;
/**
* Cancel the animation and reset to initial state
*/
cancel: () => void;
/**
* Complete the animation immediately
*/
complete: () => void;
/**
* Promise that resolves when animation completes
*/
then: (
onResolve?: () => void,
onReject?: (error: any) => void
) => Promise<void>;
}Usage Examples:
import { useAnimate } from "framer-motion";
function AnimatedComponent() {
const [scope, animate] = useAnimate();
const handleClick = async () => {
// Animate multiple elements in sequence
await animate(".card", { x: 100 }, { duration: 0.5 });
await animate(".title", { opacity: 0.5 }, { duration: 0.3 });
// Animate multiple properties
await animate(
".button",
{
scale: [1, 1.2, 1],
rotate: [0, 180, 360],
backgroundColor: ["#ff0000", "#00ff00", "#0000ff"]
},
{ duration: 1, ease: "easeInOut" }
);
};
return (
<div ref={scope}>
<div className="card">Card content</div>
<h1 className="title">Title</h1>
<button className="button" onClick={handleClick}>
Animate
</button>
</div>
);
}Creates animation controls that can be passed to motion components for imperative control.
/**
* Creates animation controls for imperative animation control
* @returns Animation controls instance
*/
function useAnimationControls(): LegacyAnimationControls;
/**
* Alias for useAnimationControls
*/
function useAnimation(): LegacyAnimationControls;
interface LegacyAnimationControls {
/**
* Start an animation
* @param definition - Animation definition or variant name
* @returns Promise that resolves when animation completes
*/
start(definition?: AnimationDefinition): Promise<any>;
/**
* Stop all running animations
*/
stop(): void;
/**
* Mount the controls (called automatically by motion components)
* @returns Cleanup function
*/
mount(): () => void;
}
type AnimationDefinition = string | {
[key: string]: any;
} | ((custom?: any) => {
[key: string]: any;
});Usage Examples:
import { motion, useAnimationControls } from "framer-motion";
function ControlledAnimation() {
const controls = useAnimationControls();
const variants = {
hidden: { opacity: 0, scale: 0.8 },
visible: { opacity: 1, scale: 1 },
pulse: {
scale: [1, 1.1, 1],
transition: { duration: 0.5, repeat: Infinity }
}
};
return (
<div>
<motion.div
animate={controls}
variants={variants}
initial="hidden"
>
Controlled animation
</motion.div>
<button onClick={() => controls.start("visible")}>
Show
</button>
<button onClick={() => controls.start("pulse")}>
Pulse
</button>
<button onClick={() => controls.stop()}>
Stop
</button>
</div>
);
}Utility for creating animation controls outside of React components.
/**
* Creates animation controls instance
* @returns New animation controls
*/
function animationControls(): LegacyAnimationControls;Minimal animation hook for WAAPI-based animations with smaller bundle size.
/**
* Minimal animation hook using Web Animations API
* @returns Animation function for WAAPI animations
*/
function useAnimateMini(): (
target: string | Element,
keyframes: Record<string, any> | Record<string, any>[],
options?: AnimationOptions
) => Animation;Usage Example:
import { useAnimateMini } from "framer-motion/mini";
function MiniAnimation() {
const animate = useAnimateMini();
const handleClick = () => {
animate(
".element",
{ transform: ["translateX(0px)", "translateX(100px)"] },
{ duration: 500, easing: "ease-out" }
);
};
return (
<div>
<div className="element">Element to animate</div>
<button onClick={handleClick}>Animate</button>
</div>
);
}Creating complex animation sequences with timing control:
// Sequential animations
async function sequence() {
await animate(".first", { x: 100 }, { duration: 0.5 });
await animate(".second", { y: 100 }, { duration: 0.5 });
await animate(".third", { rotate: 180 }, { duration: 0.5 });
}
// Parallel animations
function parallel() {
animate(".first", { x: 100 }, { duration: 0.5 });
animate(".second", { y: 100 }, { duration: 0.5, delay: 0.1 });
animate(".third", { rotate: 180 }, { duration: 0.5, delay: 0.2 });
}
// Staggered animations
function stagger() {
const elements = document.querySelectorAll(".item");
elements.forEach((element, index) => {
animate(
element,
{ opacity: 1, y: 0 },
{
duration: 0.5,
delay: index * 0.1,
ease: "easeOut"
}
);
});
}Dynamic Animation Definitions:
const controls = useAnimationControls();
// Function-based animation definition
controls.start((custom) => ({
x: custom.targetX,
y: custom.targetY,
transition: { duration: custom.duration }
}));
// Conditional animations
controls.start(isVisible ? "visible" : "hidden");
// Chained animations
controls.start("slideIn")
.then(() => controls.start("fadeIn"))
.then(() => controls.start("bounce"));Coordinated Multi-Element Animation:
function CoordinatedAnimation() {
const [scope, animate] = useAnimate();
const animateSequence = async () => {
// Animate multiple elements with precise timing
const timeline = [
[".header", { opacity: 1, y: 0 }, { duration: 0.5 }],
[".content", { opacity: 1, x: 0 }, { duration: 0.6, delay: 0.2 }],
[".footer", { opacity: 1, scale: 1 }, { duration: 0.4, delay: 0.4 }]
];
// Run animations in parallel with different delays
timeline.forEach(([target, keyframes, options]) => {
animate(target, keyframes, options);
});
};
return (
<div ref={scope}>
<div className="header" style={{ opacity: 0, y: -20 }}>Header</div>
<div className="content" style={{ opacity: 0, x: -20 }}>Content</div>
<div className="footer" style={{ opacity: 0, scale: 0.8 }}>Footer</div>
<button onClick={animateSequence}>Animate All</button>
</div>
);
}