Docs
Expandable
On hover, the image expands to show image details.
requires interactionhover
Loading...
Installation
CLI
pnpm dlx shadcn@latest add https://animata.design/r/carousel/expandable.json
Manual
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.tsxPaste the code
Open the newly created file and paste the following code:
import { type 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 delay-0 duration-300 ease-in-out",
{
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