{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "parallax-cards",
  "type": "registry:component",
  "title": "Parallax Cards",
  "author": "Toby Belhome",
  "description": "Parallax scrolling effect using overlapping cards.",
  "dependencies": [
    "lucide-react",
    "motion",
    "lenis"
  ],
  "registryDependencies": [
    "button"
  ],
  "files": [
    {
      "path": "examples/motion/components/parallax-cards/01/page.tsx",
      "content": "\"use client\";\n\nimport { useEffect, useRef } from \"react\";\nimport { ChevronDownIcon, ChevronRightIcon } from \"lucide-react\";\nimport { useScroll, cancelFrame, frame } from \"motion/react\";\nimport { ReactLenis } from \"lenis/react\";\nimport type { LenisRef } from \"lenis/react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport ParallaxCardEffect from \"./parallax-card-effect\";\nimport { cn } from \"@/lib/utils\";\n\nconst cardItems = [\n  {\n    title: \"Urban Reflections\",\n    description:\n      \"An exploration of how cities shape our perception of light, shadow, and movement. Each frame reflects the rhythm of everyday urban life.\",\n    src: \"https://plus.unsplash.com/premium_vector-1744029045529-3fcd4f715be6?q=80&w=2748&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D\",\n    className: \"bg-red-200 dark:bg-red-900\"\n  },\n  {\n    title: \"Wilderness Silence\",\n    description:\n      \"A visual journey into untouched landscapes where silence becomes the most powerful storyteller.\",\n    src: \"https://plus.unsplash.com/premium_vector-1697729849330-ef5db47d3246?q=80&w=2814&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D\",\n    className: \"bg-green-200 dark:bg-green-900\"\n  },\n  {\n    title: \"Ocean Whispers\",\n    description:\n      \"Capturing the ever-changing moods of the sea, from calm horizons to raging storms that leave a timeless imprint.\",\n    src: \"https://plus.unsplash.com/premium_vector-1697729780111-058eea198643?q=80&w=2648&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D\",\n    className: \"bg-orange-200 dark:bg-orange-900\"\n  },\n  {\n    title: \"Desert Dreams\",\n    description:\n      \"Through vast emptiness and shifting sands, this project highlights the fragile beauty of desert environments.\",\n    src: \"https://plus.unsplash.com/premium_vector-1721220820381-71da4f8b1adf?q=80&w=2360&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D\",\n    className: \"bg-indigo-200 dark:bg-indigo-900\"\n  },\n  {\n    title: \"Mountain Echoes\",\n    description:\n      \"The monumental presence of mountains and their interplay with light and atmosphere form the essence of this series.\",\n    src: \"https://plus.unsplash.com/premium_vector-1725703994559-09c72f2a317d?q=80&w=2360&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D\",\n    className: \"bg-purple-200 dark:bg-purple-900\"\n  }\n];\n\nexport type CardItemType = (typeof cardItems)[number];\n\nexport default function Page() {\n  const lenisRef = useRef<LenisRef>(null);\n  const containerRef = useRef<HTMLDivElement>(null);\n\n  const { scrollYProgress } = useScroll({\n    target: containerRef,\n    offset: [\"start start\", \"end end\"]\n  });\n\n  useEffect(() => {\n    function update(data: { timestamp: number }) {\n      const time = data.timestamp;\n      lenisRef.current?.lenis?.raf(time);\n    }\n\n    frame.update(update, true);\n\n    return () => cancelFrame(update);\n  }, []);\n\n  const ParallaxCardItem = ({ item, id }: { item: CardItemType; id: number }) => {\n    const targetScale = 1 - (cardItems.length - id) * 0.05;\n\n    return (\n      <ParallaxCardEffect\n        id={id}\n        progress={scrollYProgress}\n        range={[id * 0.25, 1]}\n        targetScale={targetScale}\n        className={cn(\"relative flex flex-col rounded-xl px-14 py-8\", item.className)}>\n        <div className=\"space-y-4 text-center\">\n          <h4 className=\"font-heading text-center text-3xl\">{item.title}</h4>\n          <p className=\"text-balance opacity-80\">{item.description}</p>\n          <Button>\n            See more <ChevronRightIcon />\n          </Button>\n        </div>\n      </ParallaxCardEffect>\n    );\n  };\n\n  return (\n    <>\n      <ReactLenis root options={{ autoRaf: false }} ref={lenisRef} />\n      <div ref={containerRef}>\n        <div className=\"flex h-[400px] items-center justify-center gap-2 text-xl\">\n          Scroll <ChevronDownIcon />\n        </div>\n        <div className=\"mx-auto max-w-2xl pt-14\">\n          {cardItems.map((cardItem, i) => (\n            <ParallaxCardItem item={cardItem} key={i} id={i} />\n          ))}\n        </div>\n      </div>\n    </>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/parallax-cards/parallax-cards-example.tsx"
    },
    {
      "path": "examples/motion/components/parallax-cards/01/parallax-card-effect.tsx",
      "content": "\"use client\";\n\nimport React from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport { motion, useTransform } from \"motion/react\";\n\ninterface CardProps {\n  id: number;\n  className?: string;\n  progress: any;\n  range: number[];\n  targetScale: number;\n  children?: React.ReactNode;\n}\n\nexport default function ParallaxCardEffect({\n  id,\n  className,\n  progress,\n  range,\n  targetScale,\n  children\n}: CardProps) {\n  const scale = useTransform(progress, range, [1, targetScale]);\n\n  return (\n    <div className=\"sticky top-0 flex h-screen items-center justify-center\">\n      <motion.div\n        style={{\n          scale,\n          top: `calc(-5vh + ${id * 30}px)`\n        }}\n        className={className}>\n        {children}\n      </motion.div>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/parallax-cards/parallax-card-effect.tsx"
    }
  ],
  "meta": {
    "isPro": false
  }
}