64 lines
2.0 KiB
TypeScript
64 lines
2.0 KiB
TypeScript
import { motion } from "motion/react";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
interface ImageBentoGalleryProps {
|
|
title?: string;
|
|
description?: string;
|
|
images: {
|
|
src: string;
|
|
alt: string;
|
|
className?: string;
|
|
}[];
|
|
}
|
|
|
|
export default function ImageBentoGallery({
|
|
title,
|
|
description,
|
|
images,
|
|
}: ImageBentoGalleryProps) {
|
|
return (
|
|
<section className="relative w-full py-16 md:py-24 lg:py-32">
|
|
<div className="container px-4 md:px-6">
|
|
<div className="flex flex-col items-center justify-center space-y-4 text-center">
|
|
{title && (
|
|
<h2 className="text-4xl md:text-5xl font-bold tracking-tighter">
|
|
{title}
|
|
</h2>
|
|
)}
|
|
{description && (
|
|
<p className="max-w-[900px] text-muted-foreground md:text-lg/relaxed lg:text-base/relaxed xl:text-lg/relaxed">
|
|
{description}
|
|
</p>
|
|
)}
|
|
</div>
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 50 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
viewport={{ once: true, amount: 0.5 }}
|
|
transition={{ duration: 0.6, delay: 0.2 }}
|
|
className="mx-auto grid max-w-5xl items-start gap-6 py-12 lg:grid-cols-3 lg:gap-12"
|
|
>
|
|
{images.map((image, index) => (
|
|
<div
|
|
key={index}
|
|
className={cn(
|
|
"relative overflow-hidden rounded-xl group aspect-video",
|
|
image.className
|
|
)}
|
|
>
|
|
<img
|
|
src={image.src}
|
|
alt={image.alt}
|
|
className="object-cover w-full h-full transition-transform duration-300 group-hover:scale-105"
|
|
/>
|
|
<div className="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent flex items-end p-4">
|
|
<h3 className="text-lg font-semibold text-background">{image.alt}</h3>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</motion.div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|