Docs
Expandable
On hover, the image expands to show image details.
requires interactionhover
Installation
Install dependencies
This uses WaveReveal for the text. Install it by following the instructions here. You can use simple text only if you don't want to use WaveReveal.
Run the following command
It will create a new file called expandable.tsx
inside the components/animata/carousel
directory.
mkdir -p components/animata/carousel && touch components/animata/carousel/expandable.tsx
Paste the code
Open the newly created file and paste the following code:
import { HTMLAttributes, useEffect, useState } from "react";
import WaveReveal from "@/animata/text/wave-reveal";
import { cn } from "@/lib/utils";
interface ImageProps extends HTMLAttributes<HTMLDivElement> {
item: { image: string; title: string };
index: number;
activeItem: number;
}
interface ExpandableProps {
list?: { image: string; title: string }[];
autoPlay?: boolean;
className?: string;
}
const List = ({ item, className, index, activeItem, ...props }: ImageProps) => {
return (
<div
className={cn(
"relative flex h-full w-20 min-w-10 cursor-pointer overflow-hidden rounded-md transition-all delay-0 duration-300 ease-in-out",
{
"flex-grow": index === activeItem,
},
className,
)}
{...props}
>
<img
src={item.image}
alt={item.title}
className={cn("h-full w-full object-cover", {
"blur-[2px]": index !== activeItem,
})}
/>
{index === activeItem && (
<div className="absolute bottom-4 left-4 min-w-fit text-white md:bottom-8 md:left-8">
<WaveReveal
duration="1000ms"
className="items-start justify-start text-xl sm:text-2xl md:text-6xl"
text={item.title}
direction="up"
/>
</div>
)}
</div>
);
};
const items = [
{
image:
"https://images.unsplash.com/photo-1541753236788-b0ac1fc5009d?q=80&w=1000&auto=format&fit=crop&ixlib=rb-4.0.3",
title: "Mountains",
},
{
image:
"https://images.unsplash.com/photo-1718027808460-7069cf0ca9ae?q=80&w=1000&auto=format&fit=crop&ixlib=rb-4.0.3",
title: "Great Wall of China",
},
{
image:
"https://images.unsplash.com/photo-1584968173934-bc0b588eb806?q=80&w=1000&auto=format&fit=crop&ixlib=rb-4.0.3",
title: "Texture & Patterns",
},
];
export default function Expandable({ list = items, autoPlay = true, className }: ExpandableProps) {
const [activeItem, setActiveItem] = useState(0);
const [isHovering, setIsHovering] = useState(false);
useEffect(() => {
if (!autoPlay) {
return;
}
const interval = setInterval(() => {
if (!isHovering) {
setActiveItem((prev) => (prev + 1) % list.length);
}
}, 5000);
return () => clearInterval(interval);
}, [autoPlay, list.length, isHovering]);
return (
<div className={cn("flex h-96 w-full gap-1", className)}>
{list.map((item, index) => (
<List
key={item.title}
item={item}
index={index}
activeItem={activeItem}
onMouseEnter={() => {
setActiveItem(index);
setIsHovering(true);
}}
onMouseLeave={() => {
setIsHovering(false);
}}
/>
))}
</div>
);
}
Credits
Built by Bibek Bhattarai