{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "scroll-reveal-shadcnui",
  "type": "registry:page",
  "title": "Scroll Reveal",
  "description": "Section that animates into view on scroll with intersection observer",
  "dependencies": [
    "framer-motion",
    "react"
  ],
  "files": [
    {
      "path": "@uitripled/react-shadcn/src/components/sections/scroll-reveal.tsx",
      "content": "\"use client\";\n\nimport {\n  AnimatePresence,\n  motion,\n  MotionConfig,\n  useInView,\n  useReducedMotion,\n  type Variants,\n} from \"framer-motion\";\nimport { Rocket, Shield, Zap } from \"lucide-react\";\nimport { useId, useMemo, useRef } from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nconst motionPresets = {\n  smooth: { type: \"spring\" as const, bounce: 0.3, duration: 0.4 },\n  bounce: { type: \"spring\" as const, bounce: 0.5, duration: 0.35 },\n  fade: { type: \"tween\" as const, ease: [0.26, 0.08, 0.25, 1] as const, duration: 0.2 },\n};\n\nconst features = [\n  {\n    icon: Zap,\n    title: \"Lightning Fast\",\n    description:\n      \"GPU-accelerated pipelines and finely tuned transitions keep every interaction responsive.\",\n  },\n  {\n    icon: Shield,\n    title: \"Secure by Default\",\n    description:\n      \"Enterprise-grade auth, encryption, and auditability woven through every flow.\",\n  },\n  {\n    icon: Rocket,\n    title: \"Effortlessly Scalable\",\n    description:\n      \"Composable primitives that adapt across teams, products, and global rollouts.\",\n  },\n];\n\ninterface ScrollRevealProps {\n  motionPreset?: keyof typeof motionPresets;\n  className?: string;\n}\n\nexport function ScrollReveal({\n  motionPreset = \"smooth\",\n  className,\n}: ScrollRevealProps) {\n  const ref = useRef<HTMLDivElement | null>(null);\n  const isInView = useInView(ref, { once: true, margin: \"-15% 0px\" });\n  const shouldReduceMotion = useReducedMotion();\n\n  const headingId = useId();\n  const descriptionId = useMemo(() => `${headingId}-description`, [headingId]);\n\n  const reducedMotionVariants: Variants = {\n    hidden: { opacity: 0 },\n    visible: { opacity: 1 },\n  };\n\n  const containerVariants: Variants = useMemo(\n    () =>\n      shouldReduceMotion\n        ? reducedMotionVariants\n        : {\n            hidden: { opacity: 0 },\n            visible: {\n              opacity: 1,\n              transition: {\n                staggerChildren: 0.1,\n                delayChildren: 0.2,\n              },\n            },\n          },\n    [shouldReduceMotion]\n  );\n\n  const itemVariants: Variants = useMemo(\n    () =>\n      shouldReduceMotion\n        ? reducedMotionVariants\n        : {\n            hidden: { opacity: 0, y: 20 },\n            visible: {\n              opacity: 1,\n              y: 0,\n              transition: { duration: 0.4 },\n            },\n          },\n    [shouldReduceMotion]\n  );\n\n  const cardVariants: Variants = {\n    idle: { y: 0 },\n    hover: { y: -4 },\n  };\n\n  const iconVariants: Variants = useMemo(\n    () =>\n      shouldReduceMotion\n        ? reducedMotionVariants\n        : {\n            hidden: { scale: 0.6, opacity: 0 },\n            visible: {\n              scale: 1,\n              opacity: 1,\n              transition: { duration: 0.4, ease: [0.18, 0.89, 0.32, 1.28] },\n            },\n          },\n    [shouldReduceMotion]\n  );\n\n  return (\n    <MotionConfig\n      transition={shouldReduceMotion ? { duration: 0 } : motionPresets[motionPreset]}\n      reducedMotion=\"user\"\n    >\n      <section\n        ref={ref}\n        aria-labelledby={headingId}\n        aria-describedby={descriptionId}\n        className={cn(\"relative w-full overflow-hidden px-4 py-12 sm:px-6 md:px-8 md:py-16 lg:py-20\", className)}\n      >\n        <motion.div\n          variants={containerVariants}\n          initial=\"hidden\"\n          animate={shouldReduceMotion || isInView ? \"visible\" : \"hidden\"}\n          className=\"mx-auto flex w-full max-w-5xl flex-col items-center text-center\"\n        >\n          {/* Header section */}\n          <motion.div variants={itemVariants} className=\"space-y-3 md:space-y-4\">\n            <motion.span\n              className=\"inline-flex items-center gap-2 rounded-full border border-border/50 bg-background/55 px-3 py-1 text-[10px] uppercase tracking-[0.2em] text-foreground/70 backdrop-blur sm:px-4 sm:py-1.5 sm:text-xs sm:tracking-[0.32em]\"\n              whileHover={shouldReduceMotion ? {} : { scale: 1.02 }}\n            >\n              Core System\n              <motion.span\n                className=\"h-1.5 w-1.5 rounded-full bg-emerald-500 sm:h-2 sm:w-2\"\n                aria-hidden\n                {...(shouldReduceMotion\n                  ? {}\n                  : {\n                      animate: { opacity: [1, 0.5, 1] },\n                      transition: { duration: 2, repeat: Infinity },\n                    })}\n              />\n            </motion.span>\n            <motion.h2\n              id={headingId}\n              className=\"text-balance text-2xl font-semibold tracking-tight text-foreground sm:text-3xl md:text-4xl lg:text-5xl\"\n            >\n              Features that elevate every launch\n            </motion.h2>\n            <motion.p\n              id={descriptionId}\n              className=\"mx-auto max-w-2xl text-sm text-foreground/70 sm:text-base md:text-lg\"\n            >\n              A glassmorphic toolkit engineered for motion-rich dashboards,\n              glowing handoffs, and resilient product experiences at scale.\n            </motion.p>\n          </motion.div>\n\n          {/* Feature cards grid */}\n          <motion.ul\n            variants={itemVariants}\n            className=\"mt-8 grid w-full grid-cols-1 gap-3 sm:grid-cols-2 md:mt-12 md:gap-4 lg:mt-14 lg:grid-cols-3 lg:gap-6\"\n            role=\"list\"\n            aria-label=\"Features\"\n          >\n            <AnimatePresence mode=\"popLayout\">\n              {features.map((feature, index) => {\n                const Icon = feature.icon;\n                return (\n                  <motion.li\n                    key={feature.title}\n                    layout={!shouldReduceMotion}\n                    initial={shouldReduceMotion ? { opacity: 1 } : { opacity: 0, y: 20 }}\n                    animate={{ opacity: 1, y: 0 }}\n                    transition={{\n                      delay: shouldReduceMotion ? 0 : 0.3 + index * 0.1,\n                      duration: 0.4,\n                    }}\n                    whileHover={shouldReduceMotion ? {} : \"hover\"}\n                    variants={cardVariants}\n                    className=\"group relative overflow-hidden rounded-xl border border-border/40 bg-background/60 p-4 text-left backdrop-blur transition-all hover:border-border/60 hover:shadow-lg md:rounded-2xl md:p-6\"\n                  >\n                    {/* Hover gradient overlay */}\n                    <div className=\"absolute inset-0 -z-10 bg-gradient-to-br from-foreground/[0.04] via-transparent to-transparent opacity-0 transition-opacity duration-300 group-hover:opacity-100\" />\n\n                    {/* Icon container */}\n                    <motion.div\n                      variants={iconVariants}\n                      className=\"relative mb-3 inline-flex h-10 w-10 items-center justify-center rounded-full bg-primary/10 md:mb-5 md:h-12 md:w-12\"\n                    >\n                      <Icon\n                        className=\"h-4 w-4 text-primary md:h-5 md:w-5\"\n                        aria-hidden\n                      />\n                    </motion.div>\n\n                    {/* Content */}\n                    <div className=\"relative space-y-1.5 md:space-y-2\">\n                      <h3 className=\"text-sm font-semibold uppercase tracking-[0.1em] text-foreground sm:text-base sm:tracking-[0.15em] md:text-lg md:normal-case md:tracking-tight\">\n                        {feature.title}\n                      </h3>\n                      <p className=\"text-xs leading-relaxed text-foreground/60 sm:text-sm\">\n                        {feature.description}\n                      </p>\n                    </div>\n                  </motion.li>\n                );\n              })}\n            </AnimatePresence>\n          </motion.ul>\n        </motion.div>\n      </section>\n    </MotionConfig>\n  );\n}\n\n",
      "type": "registry:page",
      "target": "components/uitripled/scroll-reveal-shadcnui.tsx"
    }
  ]
}