CascadeCard

→ div component that fades in/out of page based on index

https://motion.dev/docs/inview

CascadeCard.tsx

import { motion, useInView } from "framer-motion";
import { useRef } from "react";

export default function CascadeCard({ index }: { index: number }){
    const ref = useRef<HTMLDivElement | null>(null);
    const inView = useInView(ref, { margin: "-10% 0px -10% 0px", amount: 0.25 });
    
    return (
        <motion.div
        ref={ref}
        // Use variants-like behavior via animate prop to allow in/out transitions
        initial={{ opacity: 0, y: 28, scale: 0.98 }}
        animate={inView ? { opacity: 1, y: 0, scale: 1 } : { opacity: 0, y: 28, scale: 0.98 }}
        transition={{
            duration: 0.6,
            ease: [0.22, 1, 0.36, 1],
            // Stagger by index to create a cascade effect
            delay: (index % 12) * 0.20, // small wave across each screenful
        }}
        className="group relative h-48 w-full rounded-md bg-gradient-to-br from-slate-700 to-slate-800 shadow-lg ring-1 ring-white/5 overflow-hidden will-change-transform"
        >
        {/* Placeholder content — replace with your <img/> later */}
        <div className="absolute inset-0 flex items-end">
            <div className="w-full p-4 text-slate-200/90 text-sm tracking-wide flex items-center justify-between">
            <span className="font-semibold">Frame {index + 1}</span>
            <span className="opacity-70">{inView ? "in view" : "out"}</span>
            </div>
        </div>
        
        
        {/* subtle hover lift */}
        <div className="absolute inset-0 transition-transform duration-300 group-hover:scale-[1.02]" />
        </motion.div>
    );

}

Gallery Logic