{ "name": "scroll-choreography", "type": "registry:ui", "dependencies": [], "registryDependencies": [], "description": "Component for scroll-choreography", "files": [ { "path": "components/ui/scroll-choreography.tsx", "content": "\"use client\";\n\nimport { motion, useScroll, useSpring, useTransform } from \"framer-motion\";\nimport { useRef } from \"react\";\nimport { cn } from \"@workspace/ui/lib/utils\";\n\ninterface ScrollChoreographyProps {\n className?: string;\n images: {\n topLeft: string;\n topRight: string;\n bottomLeft: string;\n bottomRight: string;\n };\n}\n\nexport function ScrollChoreography({\n className,\n images,\n}: ScrollChoreographyProps) {\n const containerRef = useRef(null);\n\n const { scrollYProgress } = useScroll({\n target: containerRef,\n offset: [\"start start\", \"end end\"],\n });\n\n const smoothProgress = useSpring(scrollYProgress, {\n stiffness: 400, // Higher stiffness for a slightly faster snap\n damping: 50, // Play with damping to add a little bounce/jerk\n mass: 1.2, // Adds a bit more weight to the movement\n restDelta: 0.001,\n });\n\n // Default positions relative to center\n const xLeft = \"-20vw\";\n const xRight = \"20vw\";\n const yTop = \"-14vh\";\n const yBottom = \"14vh\";\n\n // Phase 1: 0 - 0.3 (Diagonal movement)\n // Phase 2: 0.35 - 0.65 (Stack alignment to center)\n // Phase 3: 0.7 - 0.9 (Top Right expands to full screen)\n\n // Top Left -> moves to Bottom Left, then to Center\n const tlX = useTransform(smoothProgress, [0, 0.3, 0.35, 0.65, 1], [xLeft, xLeft, xLeft, \"0vw\", \"0vw\"]);\n const tlY = useTransform(smoothProgress, [0, 0.3, 0.35, 0.65, 1], [yTop, yBottom, yBottom, \"0vh\", \"0vh\"]);\n\n // Bottom Right -> moves to Top Right, then to Center\n const brX = useTransform(smoothProgress, [0, 0.3, 0.35, 0.65, 1], [xRight, xRight, xRight, \"0vw\", \"0vw\"]);\n const brY = useTransform(smoothProgress, [0, 0.3, 0.35, 0.65, 1], [yBottom, yTop, yTop, \"0vh\", \"0vh\"]);\n\n // Bottom Left -> stays, then moves to Center\n const blX = useTransform(smoothProgress, [0, 0.3, 0.35, 0.65, 1], [xLeft, xLeft, xLeft, \"0vw\", \"0vw\"]);\n const blY = useTransform(smoothProgress, [0, 0.3, 0.35, 0.65, 1], [yBottom, yBottom, yBottom, \"0vh\", \"0vh\"]);\n\n // Top Right -> stays, then moves to Center, then expands\n const trX = useTransform(smoothProgress, [0, 0.3, 0.35, 0.65, 1], [xRight, xRight, xRight, \"0vw\", \"0vw\"]);\n const trY = useTransform(smoothProgress, [0, 0.3, 0.35, 0.65, 1], [yTop, yTop, yTop, \"0vh\", \"0vh\"]);\n\n // Top Right (Hero) scaling/expansion properties\n const heroWidth = useTransform(smoothProgress, [0.65, 0.7, 0.9, 1], [\"36vw\", \"36vw\", \"100vw\", \"100vw\"]);\n const heroHeight = useTransform(smoothProgress, [0.65, 0.7, 0.9, 1], [\"24vh\", \"24vh\", \"100vh\", \"100vh\"]);\n\n // Opacity fading for images underneath the hero as it expands\n const underImagesOpacity = useTransform(smoothProgress, [0.75, 0.85], [1, 0]);\n\n const baseImageClasses =\n \"absolute left-1/2 top-1/2 w-[36vw] h-[24vh] overflow-hidden -translate-x-1/2 -translate-y-1/2 bg-muted shadow-2xl will-change-transform\";\n\n return (\n
\n
\n
\n\n {/* Top Left Image */}\n \n \"Top\n \n\n {/* Bottom Right Image */}\n \n \"Bottom\n \n\n {/* Bottom Left Image */}\n \n \"Bottom\n \n\n {/* Top Right Image (Hero - expands at the end) */}\n \n \"Top\n \n
\n
\n
\n );\n}\n", "type": "registry:ui" } ] }