Documentation Index Fetch the complete documentation index at: https://mintlify.com/pqoqubbw/icons/llms.txt
Use this file to discover all available pages before exploring further.
Learn how to create creative, meaningful animations that enhance your icons.
What Makes a Good Animation
A good animation should:
Enhance Meaning The animation should reinforce or reveal the icon’s purpose, not just add motion for the sake of it.
Be Creative Avoid generic path length animations. Think about how the icon’s elements can move, transform, or interact.
Feel Natural Use appropriate easing, timing, and physics to make animations feel smooth and intentional.
Stay Performant Keep animations lightweight and avoid excessive complexity that could impact performance.
Avoid Generic Animations
Don’t use simple path length animations - The basic strokeDasharray/strokeDashoffset “drawing” effect is too generic and will likely result in your PR being rejected.// ❌ Avoid this generic pattern
const BAD_VARIANTS = {
normal: { pathLength: 0 },
animate: { pathLength: 1 }
};
Instead, think creatively about how the icon’s meaning can be expressed through motion.
Common Animation Patterns
Scale and Pulse
Great for icons that represent emphasis or interaction:
// Heart icon - pulses to show affection
const HeartIcon = () => {
return (
< motion.svg
variants = { {
normal: { scale: 1 },
animate: { scale: [ 1 , 1.08 , 1 ] },
} }
transition = { {
duration: 0.45 ,
repeat: 2 ,
} }
>
{ /* SVG paths */ }
</ motion.svg >
);
};
Rotation and Shake
Perfect for notifications or alert icons:
// Bell icon - rings like a real bell
const SVG_VARIANTS = {
normal: { rotate: 0 },
animate: { rotate: [ 0 , - 10 , 10 , - 10 , 0 ] },
};
const BellIcon = () => (
< motion.svg
variants = { SVG_VARIANTS }
transition = { {
duration: 0.5 ,
ease: "easeInOut" ,
} }
>
{ /* SVG paths */ }
</ motion.svg >
);
Multi-Element Animations
Animate different parts of the icon independently:
// Sparkles icon - different parts animate separately
const SPARKLE_VARIANTS = {
initial: { y: 0 , fill: "none" },
hover: {
y: [ 0 , - 1 , 0 , 0 ],
fill: "currentColor" ,
transition: { duration: 1 , bounce: 0.3 },
},
};
const STAR_VARIANTS = {
initial: { opacity: 1 , x: 0 , y: 0 },
blink : () => ({
opacity: [ 0 , 1 , 0 , 0 , 0 , 0 , 1 ],
transition: {
duration: 2 ,
type: "spring" ,
stiffness: 70 ,
damping: 10 ,
mass: 0.4 ,
},
}),
};
Position and Movement
Animate position to convey action:
// Send icon - moves as if being sent
const SendIcon = () => (
< svg >
< motion.g
variants = { {
normal: { x: 0 , y: 0 , scale: 1 },
animate: { x: 3 , y: - 3 , scale: 0.8 },
} }
transition = { { duration: 0.5 } }
>
{ /* Paper airplane paths */ }
</ motion.g >
{ /* Trail effect that appears during animation */ }
< motion.path
variants = { {
normal: { pathLength: 0 , opacity: 0 },
animate: { pathLength: 1 , opacity: 1 },
} }
stroke = "currentColor"
strokeDasharray = "2 2"
/>
</ svg >
);
Morphing Paths
Change the d attribute to morph shapes:
// Rocket icon - fire effect morphs
const FIRE_VARIANTS = {
normal: {
d: "M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z" ,
},
animate: {
d: [
"M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z" ,
"M4.5 16.5c-1.5 1.26-3 5.5-3 5.5s4.74-1 6-2.5c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z" ,
// More variations...
],
transition: {
duration: 2 ,
ease: [ 0.4 , 0 , 0.2 , 1 ],
repeat: Number .POSITIVE_INFINITY,
},
},
};
Complex Choreography
Combine multiple animations with delays:
// Rocket icon - floats with varying motion
const VARIANTS = {
normal: { x: 0 , y: 0 },
animate: {
x: [ 0 , 0 , - 3 , 2 , - 2 , 1 , - 1 , 0 ],
y: [ 0 , - 3 , 0 , - 2 , - 3 , - 1 , - 2 , 0 ],
transition: {
duration: 6 ,
ease: "easeInOut" ,
repeat: Number .POSITIVE_INFINITY,
repeatType: "reverse" ,
times: [ 0 , 0.15 , 0.3 , 0.45 , 0.6 , 0.75 , 0.9 , 1 ],
},
},
};
Framer Motion Patterns
All animations in this project use Framer Motion . Here are the key patterns:
Using Controls
Every icon uses useAnimation() for programmatic control:
const controls = useAnimation ();
// Trigger animations
controls . start ( 'animate' );
controls . start ( 'normal' );
Variants System
Define animation states using variants:
const VARIANTS : Variants = {
normal: {
// Initial/rest state
},
animate: {
// Animated state
},
};
< motion.svg
animate = { controls }
variants = { VARIANTS }
/>
Transition Options
Control timing, easing, and repetition:
transition = {{
duration : 0.5 , // Animation duration
ease : "easeInOut" , // Easing function
repeat : 2 , // Number of repeats
repeatType : "reverse" , // How to repeat
delay : 0.1 , // Delay before starting
times : [ 0 , 0.5 , 1 ], // Keyframe timing
}}
Animation Examples from the Project
Study these examples for inspiration:
Heart (icons/heart.tsx) - Simple scale pulse
Bell (icons/bell.tsx) - Rotation shake
Sparkles (icons/sparkles.tsx) - Multi-element with fills and blinks
Send (icons/send.tsx) - Position change with trail effect
Rocket (icons/rocket.tsx) - Complex floating motion with morphing fire
Zap (icons/zap.tsx) - Path drawing (used creatively, not generically)
Testing Your Animation
Test on hover - Ensure smooth enter/exit transitions
Test programmatically - Use the imperative handle to trigger animations
Check performance - Make sure animations run at 60fps
Verify responsiveness - Test at different sizes
Review on different devices - Check mobile and desktop behavior
Next Steps