Drop-in React components for hover-interactive GIF icons. Each icon decodes once and supports four playback variants — forward-and-reverse, looping, play-once, and mouse-X scrub. Designed for tool grids, nav menus, and feature showcases that need to feel alive.
Same source GIF — four different playback behaviors. Hover each preview to see it in action.
reverseOnLeavePlays forward on hover, plays backward when you leave. Feels physical, like a spring returning to rest.
Drop-in usage
<AnimatedIcon
id="video-upload"
variant="reverseOnLeave"
hovered={hovered}
className="w-24 h-24"
/>When to use: Default — tool preview cards, nav icons
loopOnHoverLoops forward continuously while hovered. Snaps back to frame 0 on leave.
Drop-in usage
<AnimatedIcon
id="video-upload"
variant="loopOnHover"
hovered={hovered}
className="w-24 h-24"
/>When to use: Loading states, processing indicators
playOncePlays through once on hover and stops on the last frame. Resets to frame 0 on leave.
Drop-in usage
<AnimatedIcon
id="video-upload"
variant="playOnce"
hovered={hovered}
className="w-24 h-24"
/>When to use: One-shot reactions, celebrations, notifications
scrubOnMouseXFrame index follows your cursor across the icon. No requestAnimationFrame — direct mapping.
Drop-in usage
<AnimatedIcon
id="video-upload"
variant="scrubOnMouseX"
hovered={hovered}
className="w-24 h-24"
/>When to use: Timeline scrubbers, before/after reveals, comparisons
Use AnimatedIconCard for tool grids. Handles hover state, link, and layout in one component.
import AnimatedIconCard from '@/components/animated-icons/AnimatedIconCard'; <AnimatedIconCard iconId="gif-pixelator" title="GIF Pixelator" description="Convert any GIF to 8-bit pixel art" to="/gif-pixelator" />
Use AnimatedIcon directly when you need custom layout or hover triggers (e.g. parent-driven hover).
import { useState } from 'react';
import AnimatedIcon from '@/components/animated-icons/AnimatedIcon';
function MyToolCard() {
const [hovered, setHovered] = useState(false);
return (
<div onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}>
<AnimatedIcon
id="gif-pixelator"
hovered={hovered}
className="w-24 h-24"
/>
</div>
);
}Every icon currently registered in lib/hoverGif/registry.js. Hover any row to preview.
| Preview | ID | Label | Variant | Speed | Tags |
|---|---|---|---|---|---|
video-upload | Video upload | reverseOnLeave | 2× | uploadvideoconverter |
Upload or paste a GIF, tweak the settings, preview it live, and copy the registry entry. Then paste it into lib/hoverGif/registry.js.
Design → preview → copy registry entry
auto from label
Live preview
Paste this into ANIMATED_ICONS in lib/hoverGif/registry.js
{
id: "my-icon",
label: "My Icon",
src: "https://your-cdn.com/icons/your-icon.gif",
variant: "reverseOnLeave",
speed: 2,
bob: true,
},Field reference
id — stable string key (required)label — short human name (required)src — GIF URL (required, must be a real .gif)variant — one of the 4 variantsspeed — 0.25..3 (default 2)bob — idle floating motion (default true)tags — optional array for filteringTips for good icons
// lib/hoverGif/registry.js
export const ANIMATED_ICONS = [
// ...existing entries
{
id: 'gif-pixelator',
label: 'GIF Pixelator',
src: 'https://your-cdn.com/icons/pixelator.gif',
variant: 'reverseOnLeave', // forward on hover, reverse on leave
speed: 2, // 2× faster than the source GIF's frame delay
bob: true, // gentle floating animation when idle
tags: ['pixel', 'remix'],
},
];