portfolio/components/ProjectShowcase.tsx
2026-02-02 13:53:49 +01:00

68 lines
2.5 KiB
TypeScript

"use client";
import { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import Image from "next/image";
export default function ProjectShowcase({ images }: { images: string[] }) {
const [index, setIndex] = useState(0);
return (
<div className="grid grid-cols-1 lg:grid-cols-12 gap-4 h-[500px]">
{/* Main Image */}
<div className="lg:col-span-9 relative overflow-hidden rounded-3xl border border-neutral-800 bg-neutral-900 group">
<AnimatePresence mode="wait">
<motion.img
key={index}
src={images[index]}
initial={{ opacity: 0, scale: 1.05 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.95 }}
transition={{ duration: 0.4, ease: "easeInOut" }}
className="absolute inset-0 h-full w-full object-cover"
/>
</AnimatePresence>
{/* Subtle Overlay Label */}
<div className="absolute bottom-4 left-4 bg-black/60 backdrop-blur-md px-3 py-1.5 rounded-full border border-white/10 opacity-0 group-hover:opacity-100 transition-opacity">
<p className="text-[10px] font-mono uppercase tracking-widest text-white/70">
View {index + 1} of {images.length}
</p>
</div>
</div>
{/* Thumbnail Column */}
<div className="lg:col-span-3 flex lg:flex-col gap-3 overflow-x-auto lg:overflow-y-auto pr-2 custom-scrollbar">
{images.map((img, i) => (
<button
key={i}
onClick={() => setIndex(i)}
className={`relative flex-shrink-0 w-24 lg:w-full aspect-video rounded-xl border-2 transition-all overflow-hidden ${
i === index
? "border-blue-500 ring-4 ring-blue-500/10"
: "border-neutral-800 opacity-40 hover:opacity-100"
}`}
>
<div className="relative h-full w-full overflow-hidden">
<Image
src={img}
alt={`Project showcase thumbnail ${i}`}
fill
className="object-cover transition-transform duration-500 group-hover:scale-105"
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>
</div>
{i === index && (
<motion.div
layoutId="active-thumb"
className="absolute inset-0 bg-blue-500/10 z-10"
/>
)}
</button>
))}
</div>
</div>
);
}