{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "sticky-feature-story",
  "type": "registry:component",
  "title": "Sticky feature story",
  "description": "A sticky scroll section where the active step highlights as you scroll and a pinned preview swaps with a step counter. Pass your own steps as props.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/premium/sticky-feature-story.tsx",
      "type": "registry:ui",
      "target": "components/ui/sticky-feature-story.tsx",
      "content": "\"use client\"\nimport * as React from \"react\"\nimport { motion, useScroll, useTransform, useReducedMotion } from \"motion/react\"\nimport { cn } from \"@/lib/utils\"\n\ntype Step = { title: string; body: string; label: string }\n\nfunction StickyFeatureStory({\n  steps = [\n    { label: \"01\", title: \"Compose free\", body: \"Ship product UI from the MIT kit — tables, AI, billing, shells.\" },\n    { label: \"02\", title: \"Invite the team\", body: \"Bring everyone in with one link. Roles and permissions are already set.\" },\n    { label: \"03\", title: \"Ship it\", body: \"Publish when you are ready. Roll back in one click if you are not.\" },\n  ],\n  className,\n}: {\n  steps?: Step[]\n  className?: string\n}) {\n  const reduce = useReducedMotion()\n  const ref = React.useRef<HTMLDivElement>(null)\n  const { scrollYProgress } = useScroll({ target: ref, offset: [\"start start\", \"end end\"] })\n  const active = useTransform(scrollYProgress, [0, 0.33, 0.66, 1], [0, 1, 2, 2])\n  const [idx, setIdx] = React.useState(0)\n  React.useEffect(() => {\n    if (reduce) return\n    return active.on(\"change\", (v) => setIdx(Math.round(v)))\n  }, [active, reduce])\n\n  return (\n    <div\n      ref={ref}\n      data-slot=\"sticky-feature-story\"\n      data-tier=\"premium\"\n      className={cn(\"relative\", className)}\n      style={{ height: reduce ? undefined : `${steps.length * 90}vh` }}\n    >\n      <div className={cn(\"grid gap-8 lg:grid-cols-2\", reduce ? \"\" : \"sticky top-16 h-[70vh] items-center\")}>\n        <div className=\"space-y-6\">\n          {steps.map((s, i) => (\n            <motion.div\n              key={s.label}\n              animate={reduce ? undefined : { x: i === idx ? 0 : -4 }}\n              transition={{ duration: 0.35 }}\n              className={cn(\n                \"border-l pl-4\",\n                i === idx ? \"border-accent\" : \"border-border\"\n              )}\n            >\n              <p className={cn(\"text-xs font-medium tracking-[0.01em] uppercase\", i === idx ? \"text-fg\" : \"text-fg-muted\")}>{s.label}</p>\n              <h3 className={cn(\"mt-1 text-2xl font-medium tracking-[-0.018em]\", i === idx ? \"text-fg\" : \"text-fg-muted\")}>{s.title}</h3>\n              <p className=\"mt-2 text-sm leading-[1.55] text-fg-muted\">{s.body}</p>\n            </motion.div>\n          ))}\n        </div>\n        <div className=\"relative aspect-[4/3] overflow-hidden rounded-2xl border border-border bg-sunken\">\n          <div className=\"absolute inset-0 bg-[radial-gradient(circle_at_30%_20%,color-mix(in_oklch,var(--accent)_18%,transparent),transparent_55%)]\" aria-hidden />\n          <div className=\"absolute inset-4 rounded-xl border border-border bg-surface shadow-highlight\">\n            <div className=\"flex h-9 items-center gap-1.5 border-b border-border px-3\">\n              <span className=\"size-2 rounded-full bg-fg-subtle/40\" />\n              <span className=\"size-2 rounded-full bg-fg-subtle/40\" />\n              <span className=\"size-2 rounded-full bg-fg-subtle/40\" />\n            </div>\n            <div className=\"space-y-3 p-4\">\n              <motion.div\n                key={idx}\n                initial={reduce ? false : { opacity: 0, y: 8 }}\n                animate={{ opacity: 1, y: 0 }}\n                className=\"h-3 w-2/3 rounded bg-fg/10\"\n              />\n              <div className=\"h-3 w-1/2 rounded bg-fg/5\" />\n              <div className=\"mt-6 grid grid-cols-3 gap-2\">\n                {[0, 1, 2].map((i) => (\n                  <div\n                    key={i}\n                    className={cn(\n                      \"aspect-square rounded-lg border border-border bg-sunken\",\n                      i === idx % 3 && \"border-accent/40 bg-accent/10\"\n                    )}\n                  />\n                ))}\n              </div>\n            </div>\n          </div>\n          <p className=\"absolute right-4 bottom-4 text-xs font-medium tabular-nums text-fg-muted\">\n            {String(idx + 1).padStart(2, \"0\")} / {String(steps.length).padStart(2, \"0\")}\n          </p>\n        </div>\n      </div>\n    </div>\n  )\n}\nexport { StickyFeatureStory }\n"
    }
  ]
}
