Container Scroll
Screenshot panel that rotates flat as it scrolls into view.
0.8 KB gzippedDeps: motion/reactReduced-motion safeBase UI & Radix compatible
Your screenshot
Installation
npx shadcn@latest add https://innsite.com.mx/r/container-scroll.jsonInstalls with: motion
Source
"use client";
import { useRef } from "react";
import { motion, useReducedMotion, useScroll, useTransform } from "motion/react";
import { cn } from "@/lib/utils";
interface ContainerScrollProps {
/** Headline area above the panel */
header?: React.ReactNode;
children: React.ReactNode;
className?: string;
}
/**
* Screenshot panel that starts tilted back in 3D and rotates flat as it
* scrolls into view — the standard "here is the product" hero moment.
*/
export function ContainerScroll({
header,
children,
className,
}: ContainerScrollProps) {
const ref = useRef<HTMLDivElement>(null);
const reducedMotion = useReducedMotion();
const { scrollYProgress } = useScroll({
target: ref,
offset: ["start end", "end start"],
});
const rotateX = useTransform(scrollYProgress, [0, 0.45], [26, 0]);
const scale = useTransform(scrollYProgress, [0, 0.45], [0.92, 1]);
const translateY = useTransform(scrollYProgress, [0, 0.45], [40, 0]);
return (
<div
ref={ref}
data-slot="container-scroll"
className={cn("flex flex-col items-center", className)}
>
{header && (
<motion.div
style={reducedMotion ? undefined : { y: translateY }}
className="mb-10 text-center"
>
{header}
</motion.div>
)}
<motion.div
style={
reducedMotion
? undefined
: { rotateX, scale, transformPerspective: 1200 }
}
className="w-full origin-top rounded-2xl border bg-card p-2 shadow-2xl shadow-brand/10 will-change-transform"
>
<div className="overflow-hidden rounded-xl border bg-muted">
{children}
</div>
</motion.div>
</div>
);
}

