Dual Animated Icon

Interactive wrapper that smoothly swaps between two icons on hover or click with fluid spring micro-interactions.

Animated Icons Dependency

This component works with any icon library (Lucide, Hugeicons, Radix, etc.). For interactive stroke/path micro-animations, it connects directly with icons from @animate-ui/react (or components/animate-ui/icons).

npm i @animate-ui/react
Click
1import { DualAnimatedIcon } from "@/components/dual-animated-icon";
2import { Copy } from "@/components/animate-ui/icons/copy";
3import { CheckCheck } from "@/components/animate-ui/icons/check-check";
4 
5export default function DualAnimatedIconDemo() {
6 return (
7 <div className="flex items-center gap-6">
8 {/* Click Trigger */}
9 <DualAnimatedIcon
10 iconA={Copy}
11 iconB={CheckCheck}
12 trigger="click"
13 size={20}
14 activeIconClassName="text-emerald-500"
15 />
16 
17 {/* Hover Trigger */}
18 <DualAnimatedIcon
19 iconA={Copy}
20 iconB={CheckCheck}
21 trigger="hover"
22 size={20}
23 activeIconClassName="text-emerald-500"
24 />
25 </div>
26 );
27}

Installation

bunx --bun shadcn@latest add https://ashutoshtiwari.me/r/dual-animated-icon.json

Usage

1import { DualAnimatedIcon } from "@/components/dual-animated-icon"
1<DualAnimatedIcon iconA={Copy} iconB={CheckCheck} trigger="click" />

API Reference

PropTypeDefaultDescription
iconAReactNode | ComponentTypeundefinedFirst icon component or node rendered in the default state.
iconBReactNode | ComponentTypeundefinedSecond icon component or node rendered in the active state.
trigger"click" | "hover" | "controlled""click"Interaction mode that triggers swapping between the two icons.
activebooleanundefinedControlled boolean state for programmatic icon switching.
onToggle(active: boolean) => voidundefinedCallback fired whenever the active icon state changes.
sizenumber16Icon width and height bounding box in pixels.
animateOnHoverbooleantrueWhether the default icon plays its micro-animation when hovered.
transitionDurationnumber0.18Duration of the icon swap spring transition in seconds.
as"span" | "div" | "button""span"Underlying HTML element tag to render as.
iconClassNamestring""Additional CSS classes applied to the default icon container.
activeIconClassNamestring""Additional CSS classes applied to the active icon container.
classNamestring""Additional CSS classes applied to the wrapper element.