The ImageTrail is an interactive component that displays a trail of images following the user's mouse cursor with physics-based momentum. It supports customized keyframe animations, distance thresholds, and custom stacking orders.
Preview
Usage
Installation
$ pnpm dlx shadcn add https://klarden.vercel.app/r/image-trail.json
Basic Example
import { ImageTrail, ImageTrailItem } from "@/components/image-trail";
const IMAGES = [
"/images/trail-1.jpg",
"/images/trail-2.jpg",
"/images/trail-3.jpg",
"/images/trail-4.jpg",
"/images/trail-5.jpg",
];
export default function App() {
return (
<ImageTrail
threshold={90}
intensity={0.2}
repeatChildren={12}
keyframes={{
scale: [0.3, 1, 1, 0.3],
rotate: [0, -10, 10, 0],
opacity: [0, 1, 1, 0],
}}
keyframesOptions={{
duration: 1.2,
times: [0, 0.05, 0.85, 1],
ease: "easeOut",
}}
trailElementAnimationKeyframes={{
x: { duration: 0.35, type: "tween", ease: "easeOut" },
y: { duration: 0.35, type: "tween", ease: "easeOut" },
}}
>
{IMAGES.map((src, index) => (
<ImageTrailItem
key={index}
className="w-32 h-32 sm:w-40 sm:h-40 shadow-2xl overflow-hidden bg-zinc-200 dark:bg-zinc-800"
>
<img
src={src}
alt={`Trail photo ${index + 1}`}
className="w-full h-full object-cover pointer-events-none select-none"
/>
</ImageTrailItem>
))}
</ImageTrail>
);
}
Properties
| Prop | Type | Default | Description |
|---|---|---|---|
as | ElementType | "div" | HTML element to render the container as. |
threshold | number | 100 | Distance in pixels the mouse must travel to spawn the next element. |
intensity | number | 0.3 | Momentum factor (0.0001 to 1.0) for tracking lag. Lower is smoother. |
keyframes | DOMKeyframesDefinition | undefined | Framer Motion keyframes defining the animation sequence. |
keyframesOptions | AnimationOptions | undefined | Framer Motion options for the keyframes animation. |
trailElementAnimationKeyframes | object | tween/easeOut | Framer Motion options for the tracking movement. |
repeatChildren | number | 3 | Number of times children are duplicated to prevent trail gaps. |
baseZIndex | number | 0 | Starting z-index for the trailing items. |
zIndexDirection | "new-on-top" | "old-on-top" | "new-on-top" | Stacking behavior ('new-on-top' or 'old-on-top'). |




