Triggers
Six ways to fire the animation - hover, click, mount, in-view, parent-hover, manual.
The trigger prop selects when the animation fires. Default is "hover".
<Heart trigger="hover" /> // default
<Heart trigger="click" />
<Heart trigger="mount" />
<Heart trigger="in-view" />
<Heart trigger="parent-hover" />
<Heart trigger="manual" />hover (default)
Animation plays while the cursor is over the icon. Standard behavior.
<Heart trigger="hover" />On touch devices there's no hover. Use click or mount for mobile-friendly motion.
click
Replays the draw on every click. The cursor changes to pointer automatically.
<Bell trigger="click" />Useful for action confirmations: success checkmarks, "added to cart," etc.
mount
Animates once on first paint. Great for hero icons or page intros.
<Star trigger="mount" />Refresh the page to see it again. Combine with delay to stagger multiple mount-triggered icons:
<Heart trigger="mount" delay={0} />
<Star trigger="mount" delay={0.2} />
<Bell trigger="mount" delay={0.4} />in-view
Animates each time the icon scrolls into the viewport. Built on IntersectionObserver. Scroll the demo out of view and back in to see it replay.
<Zap trigger="in-view" />Useful for landing pages where icons should animate as the user scrolls down.
parent-hover
Animate the icon when a parent element is hovered, not just the icon itself. This is the trigger you want for icons inside buttons or cards.
How it works: the icon walks up the DOM to find the nearest ancestor with data-motion-icon-group and binds to its hover events.
<button
data-motion-icon-group
className="inline-flex items-center gap-2 rounded-md bg-zinc-900 px-4 py-2 text-white"
>
Continue
<Send size={18} trigger="parent-hover" />
</button>You can use any element as the group root — <button>, <a>, <div>, <li>. The constant PARENT_HOVER_ATTR is also exported from the package if you'd rather reference it programmatically.
manual
You control when the animation fires via an imperative ref. The ref exposes a MotionIconHandle:
interface MotionIconHandle {
play: () => void;
reset: () => void;
node: SVGSVGElement | null;
}"use client";
import { useRef } from "react";
import { Rocket } from "lucide-motion";
import type { MotionIconHandle } from "lucide-motion";
export function LaunchButton() {
const iconRef = useRef<MotionIconHandle>(null);
return (
<div className="flex items-center gap-4">
<Rocket size={48} trigger="manual" ref={iconRef} />
<button onClick={() => iconRef.current?.play()}>
Launch
</button>
</div>
);
}Use this for animations driven by external events — form submission success, route transitions, websocket messages, etc.
Choosing a trigger
| Goal | Trigger |
|---|---|
| Default delightful hover | hover |
| Replay on action / mobile-friendly | click |
| Hero / page-load animation | mount |
| Scroll-driven reveal | in-view |
| Animate icon inside a button | parent-hover |
| External-event-driven | manual |