{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "container-scroll",
  "title": "Container Scroll",
  "author": "Ballmac <https://ui.ballmac.com>",
  "description": "A showcase frame that starts tilted back in 3D and flattens to face the reader as it scrolls into view, with a title that lifts alongside.",
  "dependencies": [
    "motion@^12"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/ballmac/components/container-scroll.tsx",
      "content": "// Ballmac UI: Container Scroll. https://ui.ballmac.com/components/container-scroll\n\"use client\";\n\nimport * as React from \"react\";\nimport { motion, useReducedMotion, useScroll, useTransform } from \"motion/react\";\nimport { cn } from \"@/lib/utils\";\n\ntype ContainerScrollProps = Omit<React.ComponentProps<\"div\">, \"title\"> & {\n  /** Heading above the frame. It slides up slightly as the frame flattens. */\n  title?: React.ReactNode;\n  /** A scrollable element to track instead of the page. */\n  container?: React.RefObject<HTMLElement | null>;\n  /** Starting tilt of the frame in degrees. */\n  tilt?: number;\n  /** Classes for the frame that holds the children. */\n  frameClassName?: string;\n};\n\n/**\n * A showcase frame that starts tilted back in 3D and flattens to face the reader as it scrolls into view.\n * Put a screenshot, video or live product demo inside. Under reduced motion the frame is flat from the start.\n */\nfunction ContainerScroll({ title, container, tilt = 22, frameClassName, className, children, ...props }: ContainerScrollProps) {\n  const reduce = useReducedMotion();\n  const ref = React.useRef<HTMLDivElement>(null);\n  const { scrollYProgress } = useScroll({\n    target: ref,\n    container,\n    offset: [\"start end\", \"center center\"],\n  });\n  const rotate = useTransform(scrollYProgress, [0, 1], [tilt, 0]);\n  const scale = useTransform(scrollYProgress, [0, 1], [0.92, 1]);\n  const lift = useTransform(scrollYProgress, [0, 1], [0, -24]);\n  return (\n    <div\n      ref={ref}\n      data-slot=\"container-scroll\"\n      className={cn(\"flex w-full flex-col items-center gap-8 py-10 [perspective:1100px]\", className)}\n      {...props}\n    >\n      {title && (\n        <motion.div style={reduce ? undefined : { y: lift }} className=\"max-w-2xl text-center text-balance\">\n          {title}\n        </motion.div>\n      )}\n      <motion.div\n        data-slot=\"container-scroll-frame\"\n        style={reduce ? undefined : { rotateX: rotate, scale, transformOrigin: \"50% 100%\" }}\n        className={cn(\n          \"w-full max-w-4xl overflow-hidden rounded-[1.75rem] border bg-card p-2 shadow-[0_0_0_1px_rgb(0_0_0/0.03),0_30px_80px_-30px_rgb(0_0_0/0.35),0_12px_24px_-12px_rgb(0_0_0/0.15)] sm:p-3\",\n          frameClassName,\n        )}\n      >\n        <div className=\"overflow-hidden rounded-[1.25rem] border bg-background\">{children}</div>\n      </motion.div>\n    </div>\n  );\n}\n\nexport { ContainerScroll, type ContainerScrollProps };\n",
      "type": "registry:ui",
      "target": "@components/ballmac/container-scroll.tsx"
    }
  ],
  "meta": {
    "schema": 1,
    "tier": "free",
    "tags": [
      "3d",
      "scroll",
      "hero",
      "showcase"
    ],
    "version": "1.0.0",
    "updated": "2026-09-30",
    "ai": {
      "summary": "<ContainerScroll title={...}>{screenshot or live demo}</ContainerScroll>. tilt sets the starting angle; container tracks a scrollable element.",
      "whenToUse": [
        "Product hero sections",
        "Showing a dashboard or app screenshot"
      ],
      "whenNotToUse": [
        "Content that must stay flat and readable at all times",
        "Pages that scroll inside nested containers without passing container"
      ],
      "composesWith": [
        "browser-frame",
        "sticky-scroll",
        "bento-grid"
      ],
      "a11y": [
        {
          "keys": "Reduced motion",
          "action": "The frame is flat from the start, with no transform"
        },
        {
          "keys": "Content",
          "action": "Children stay real, selectable, focusable content"
        }
      ],
      "customization": [
        "tilt",
        "title slot",
        "frameClassName",
        "container"
      ]
    },
    "examples": [
      "container-scroll-demo",
      "container-scroll-states"
    ],
    "url": "https://ui.ballmac.com/components/container-scroll"
  },
  "categories": [
    "layout"
  ],
  "type": "registry:ui"
}