{
  "name": "card-stack",
  "type": "registry:component",
  "dependencies": [
    "motion"
  ],
  "files": [
    {
      "type": "registry:component",
      "content": "\"use client\";\n\n/**\n * @author: @dorianbaffier\n * @description: Card Stack\n * @version: 1.1.0\n * @date: 2025-06-26\n * @license: MIT\n * @website: https://kokonutui.com\n * @github: https://github.com/kokonut-labs/kokonutui\n */\n\nimport { motion, useReducedMotion } from \"motion/react\";\nimport Image from \"next/image\";\nimport { useState } from \"react\";\nimport { cn } from \"@/lib/utils\";\n\ninterface Specification {\n  label: string;\n  value: string;\n}\n\ninterface Product {\n  id: string;\n  title: string;\n  subtitle: string;\n  description: string;\n  image: string;\n  specs: Specification[];\n}\n\nconst products: Product[] = [\n  {\n    id: \"instant-pay\",\n    title: \"Quick Pay\",\n    subtitle: \"Instant Transfers\",\n    description:\n      \"Move money in seconds with bank-grade security and zero surprises.\",\n    image: \"/undraw.svg\",\n    specs: [\n      { label: \"Speed\", value: \"Instant\" },\n      { label: \"Security\", value: \"256-bit\" },\n      { label: \"Limit\", value: \"$50,000\" },\n      { label: \"Fee\", value: \"0.5%\" },\n    ],\n  },\n  {\n    id: \"crypto-pay\",\n    title: \"Crypto Pay\",\n    subtitle: \"Web3 Payments\",\n    description:\n      \"Accept crypto across every major chain with optimized gas routing.\",\n    image:\n      \"https://images.unsplash.com/photo-1527443224154-c4a3942d3acf?w=800&auto=format&fit=crop&q=80\",\n    specs: [\n      { label: \"Network\", value: \"Multi-chain\" },\n      { label: \"Gas\", value: \"Optimized\" },\n      { label: \"Support\", value: \"24/7\" },\n      { label: \"Security\", value: \"Top-tier\" },\n    ],\n  },\n  {\n    id: \"business-pay\",\n    title: \"Business Pay\",\n    subtitle: \"Enterprise Solutions\",\n    description:\n      \"Built for high-volume teams with custom APIs and premium support.\",\n    image:\n      \"https://images.unsplash.com/photo-1544244015-0df4b3ffc6b0?w=800&auto=format&fit=crop&q=80\",\n    specs: [\n      { label: \"Volume\", value: \"Unlimited\" },\n      { label: \"API\", value: \"REST/SDK\" },\n      { label: \"Support\", value: \"Premium\" },\n      { label: \"Features\", value: \"Custom\" },\n    ],\n  },\n  {\n    id: \"global-pay\",\n    title: \"Global Pay\",\n    subtitle: \"International Transfers\",\n    description:\n      \"Send to 180+ countries with real-time FX and same-day settlement.\",\n    image:\n      \"https://images.unsplash.com/photo-1629131726692-1accd0c53ce0?w=800&auto=format&fit=crop&q=80\",\n    specs: [\n      { label: \"Countries\", value: \"180+\" },\n      { label: \"FX Rate\", value: \"Real-time\" },\n      { label: \"Speed\", value: \"Same-day\" },\n      { label: \"Support\", value: \"Local\" },\n    ],\n  },\n];\n\nconst CARD_WIDTH = 320;\nconst CARD_OVERLAP = 240;\n\ninterface CardProps {\n  product: Product;\n  index: number;\n  totalCards: number;\n  isExpanded: boolean;\n  reducedMotion: boolean;\n}\n\nconst Card = ({\n  product,\n  index,\n  totalCards,\n  isExpanded,\n  reducedMotion,\n}: CardProps) => {\n  const centerOffset = (totalCards - 1) * 5;\n  const defaultX = index * 10 - centerOffset;\n  const defaultY = index * 2;\n  const defaultRotate = index * 1.5;\n\n  const totalExpandedWidth =\n    CARD_WIDTH + (totalCards - 1) * (CARD_WIDTH - CARD_OVERLAP);\n  const expandedCenterOffset = totalExpandedWidth / 2;\n\n  const spreadX =\n    index * (CARD_WIDTH - CARD_OVERLAP) - expandedCenterOffset + CARD_WIDTH / 2;\n  const spreadRotate = index * 5 - (totalCards - 1) * 2.5;\n\n  const collapsedPose = {\n    x: defaultX,\n    y: defaultY,\n    rotate: reducedMotion ? 0 : defaultRotate,\n    scale: 1,\n  };\n\n  const expandedPose = {\n    x: spreadX,\n    y: 0,\n    rotate: reducedMotion ? 0 : spreadRotate,\n    scale: 1,\n  };\n\n  const isSvg = product.image.endsWith(\".svg\");\n\n  return (\n    <motion.div\n      animate={{\n        ...(isExpanded ? expandedPose : collapsedPose),\n        zIndex: totalCards - index,\n      }}\n      className={cn(\n        \"absolute inset-0 w-full rounded-2xl p-6\",\n        \"bg-white/60 dark:bg-neutral-900/60\",\n        \"border border-white/20 dark:border-neutral-800/40\",\n        \"backdrop-blur-xl backdrop-saturate-150\",\n        \"shadow-[0_8px_20px_rgb(0,0,0,0.08)] dark:shadow-[0_8px_20px_rgb(0,0,0,0.3)]\",\n        \"hover:border-white/30 dark:hover:border-neutral-700/30\",\n        \"hover:shadow-[0_12px_40px_rgb(0,0,0,0.12)] dark:hover:shadow-[0_12px_40px_rgb(0,0,0,0.4)]\",\n        \"transition-[border-color,box-shadow] duration-300 ease-out\",\n        \"transform-gpu overflow-hidden\"\n      )}\n      initial={collapsedPose}\n      style={{\n        maxWidth: `${CARD_WIDTH}px`,\n        left: \"50%\",\n        marginLeft: `-${CARD_WIDTH / 2}px`,\n      }}\n      transition={\n        reducedMotion\n          ? { duration: 0.2, ease: \"easeOut\" }\n          : {\n              type: \"spring\",\n              stiffness: 220,\n              damping: 28,\n              mass: 1,\n              delay: isExpanded ? index * 0.04 : 0,\n            }\n      }\n    >\n      <div className=\"relative z-10\">\n        <dl className=\"mb-4 grid grid-cols-4 justify-center gap-2\">\n          {product.specs.map((spec) => (\n            <div\n              className=\"flex flex-col items-start text-left text-[10px]\"\n              key={spec.label}\n            >\n              <dd className=\"w-full text-left font-medium text-gray-500 dark:text-gray-400\">\n                {spec.value}\n              </dd>\n              <dt className=\"mb-0.5 w-full text-left text-gray-900 dark:text-gray-100\">\n                {spec.label}\n              </dt>\n            </div>\n          ))}\n        </dl>\n\n        <div\n          className={cn(\n            \"relative aspect-[16/11] w-full overflow-hidden rounded-lg\",\n            \"bg-neutral-100 dark:bg-neutral-900\",\n            \"border border-neutral-200/50 dark:border-neutral-700/50\",\n            \"shadow-inner\"\n          )}\n        >\n          <Image\n            alt={product.description}\n            className=\"object-cover\"\n            fill\n            sizes=\"320px\"\n            src={product.image}\n            unoptimized={isSvg}\n          />\n        </div>\n\n        <div className=\"mt-4\">\n          <div className=\"space-y-1\">\n            <span className=\"block text-left font-bold text-3xl text-gray-900 tracking-tight dark:text-white\">\n              {product.title}\n            </span>\n            <span className=\"block text-left font-semibold text-3xl text-gray-500 tracking-tight dark:text-gray-400\">\n              {product.subtitle}\n            </span>\n          </div>\n          <p className=\"mt-2 text-left text-gray-500 text-sm dark:text-gray-400\">\n            {product.description}\n          </p>\n        </div>\n      </div>\n    </motion.div>\n  );\n};\n\ninterface CardStackProps {\n  className?: string;\n}\n\nexport default function CardStackExample({ className }: CardStackProps) {\n  const [isExpanded, setIsExpanded] = useState(false);\n  const reducedMotion = useReducedMotion() ?? false;\n\n  const handleToggle = () => setIsExpanded((prev) => !prev);\n\n  return (\n    <button\n      aria-expanded={isExpanded}\n      aria-label={isExpanded ? \"Collapse card stack\" : \"Expand card stack\"}\n      className={cn(\n        \"relative mx-auto cursor-pointer\",\n        \"min-h-[440px] w-full max-w-[90vw]\",\n        \"md:max-w-[1200px]\",\n        \"appearance-none border-0 bg-transparent p-0\",\n        \"mb-8 flex items-center justify-center\",\n        className\n      )}\n      onClick={handleToggle}\n      type=\"button\"\n    >\n      {products.map((product, index) => (\n        <Card\n          index={index}\n          isExpanded={isExpanded}\n          key={product.id}\n          product={product}\n          reducedMotion={reducedMotion}\n          totalCards={products.length}\n        />\n      ))}\n    </button>\n  );\n}\n",
      "path": "/components/kokonutui/card-stack.tsx",
      "target": "components/kokonutui/card-stack.tsx"
    }
  ]
}