{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "folder-component",
  "title": "Folder Component",
  "description": "An animated folder whose cards fan out on hover and lift open on click, with a 3D-tilted flap. Supports color and size (sm/md/lg) props.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "components/ui/folder-component.tsx",
      "content": "\"use client\";\n\nimport React, { useState } from \"react\";\nimport { motion } from \"motion/react\";\nimport { cn } from \"@/lib/utils\";\n\nconst themes = {\n  black: {\n    backFill: \"black\",\n    backInsetColor: \"0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.37 0\",\n    backInsetShadow: \"inset 0 0 6px 2px rgba(255,255,255,0.37)\",\n    flapFill: \"#292929\",\n    flapFillOpacity: 0.25,\n    flapStroke: \"#979797\",\n    flapInsetColor: \"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.08 0\",\n    cardFill: \"#F1F1F1\",\n    cardStroke: \"#E0E0E0\",\n    cardLineFill: \"#D4D4D4\",\n    cardInsetColor: \"0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0\",\n  },\n  white: {\n    backFill: \"#ffffff\",\n    backInsetColor: \"0 0 0 0 0.7 0 0 0 0 0.7 0 0 0 0 0.7 0 0 0 0.25 0\",\n    backInsetShadow: \"inset 0 0 6px 2px rgba(178,178,178,0.25)\",\n    flapFill: \"#f5f5f5\",\n    flapFillOpacity: 0.85,\n    flapStroke: \"#d4d4d4\",\n    flapInsetColor: \"0 0 0 0 0.6 0 0 0 0 0.6 0 0 0 0 0.6 0 0 0 0.15 0\",\n    cardFill: \"#262626\",\n    cardStroke: \"#404040\",\n    cardLineFill: \"#737373\",\n    cardInsetColor: \"0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.15 0\",\n  },\n  blue: {\n    backFill: \"#50B1FD\",\n    backInsetColor: \"0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.35 0\",\n    backInsetShadow: \"inset 0 0 6px 2px rgba(255,255,255,0.35)\",\n    flapFill: \"#3a9ae8\",\n    flapFillOpacity: 0.45,\n    flapStroke: \"#7ec8ff\",\n    flapInsetColor: \"0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.12 0\",\n    cardFill: \"#F1F1F1\",\n    cardStroke: \"#E0E0E0\",\n    cardLineFill: \"#D4D4D4\",\n    cardInsetColor: \"0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0\",\n  },\n} as const;\n\nconst sizeScales = {\n  sm: 0.65,\n  md: 1,\n  lg: 1.35,\n} as const;\n\ntype FolderComponentProps = Omit<React.ComponentProps<\"div\">, \"color\"> & {\n  color?: \"black\" | \"white\" | \"blue\";\n  size?: \"sm\" | \"md\" | \"lg\";\n};\n\nconst BASE_WIDTH = 321;\nconst BASE_HEIGHT = 270;\n\nconst FLAP_PATH =\n  \"M0 25C0 11.1929 11.1929 0 25 0H136.084C143.044 0 149.689 2.90139 154.42 8.00608L178.08 33.5343C182.811 38.639 189.456 41.5404 196.416 41.5404H296C309.807 41.5404 321 52.7333 321 66.5404V216C321 229.807 309.807 241 296 241H25C11.1929 241 0 229.807 0 216V25Z\";\n\nconst FolderComponent = ({\n  color = \"black\",\n  size = \"md\",\n  className,\n  ...props\n}: FolderComponentProps) => {\n  const theme = themes[color] ?? themes.black;\n  const scale = sizeScales[size];\n  const [isHovered, setIsHovered] = useState(false);\n  const [isOpen, setIsOpen] = useState(false);\n\n  return (\n    <div\n      data-slot=\"folder\"\n      className={cn(\n        \"relative w-full h-full flex items-center justify-center\",\n        className,\n      )}\n      {...props}\n    >\n      <div\n        className=\"relative cursor-pointer select-none\"\n        style={{\n          width: BASE_WIDTH * scale,\n          height: BASE_HEIGHT * scale,\n          touchAction: \"manipulation\",\n          WebkitTapHighlightColor: \"transparent\",\n        }}\n        onMouseEnter={() => setIsHovered(true)}\n        onMouseLeave={() => {\n          setIsHovered(false);\n          setIsOpen(false);\n        }}\n        onClick={() => setIsOpen((o) => !o)}\n      >\n        <div\n          className=\"absolute top-1/2 left-1/2\"\n          style={{\n            width: BASE_WIDTH,\n            height: BASE_HEIGHT,\n            transform: `translate(-50%, -50%) scale(${scale})`,\n            perspective: 800 * scale,\n          }}\n        >\n          <div className=\"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2\">\n            <div\n              style={{\n                width: BASE_WIDTH,\n                height: BASE_HEIGHT,\n                borderRadius: 25,\n                backgroundColor: theme.backFill,\n                boxShadow: theme.backInsetShadow,\n              }}\n            />\n          </div>\n\n          <div className=\"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 flex items-center justify-center\">\n            <motion.div\n              className=\"absolute\"\n              animate={{\n                y: isOpen ? -160 : isHovered ? -30 : -10,\n                x: isOpen ? 70 : 40,\n                rotate: isOpen ? 18 : isHovered ? 14 : 10,\n              }}\n              transition={{\n                type: \"spring\",\n                stiffness: 120,\n                damping: 13,\n                delay: isOpen ? 0.1 : isHovered ? 0.12 : 0,\n              }}\n            >\n              <Card id={1} theme={theme} />\n            </motion.div>\n            <motion.div\n              className=\"absolute\"\n              animate={{\n                y: isOpen ? -180 : isHovered ? -35 : -20,\n                x: isOpen ? 0 : 3,\n                rotate: isOpen ? -3 : isHovered ? -1 : 2,\n              }}\n              transition={{\n                type: \"spring\",\n                stiffness: 120,\n                damping: 13,\n                delay: isOpen ? 0.05 : isHovered ? 0.06 : 0,\n              }}\n            >\n              <Card id={2} theme={theme} />\n            </motion.div>\n            <motion.div\n              className=\"absolute\"\n              animate={{\n                y: isOpen ? -170 : isHovered ? -44 : -22,\n                x: isOpen ? -65 : -40,\n                rotate: isOpen ? -14 : isHovered ? -9 : -5,\n              }}\n              transition={{\n                type: \"spring\",\n                stiffness: 120,\n                damping: 13,\n                delay: isOpen ? 0 : 0,\n              }}\n            >\n              <Card id={3} theme={theme} />\n            </motion.div>\n          </div>\n\n          <motion.div\n            className=\"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 mt-4\"\n            style={{\n              transformOrigin: \"bottom center\",\n              transformStyle: \"preserve-3d\",\n              width: 321,\n              height: 241,\n            }}\n            animate={{ rotateX: isOpen ? -55 : isHovered ? -45 : -15 }}\n            transition={{ type: \"spring\", stiffness: 120, damping: 14 }}\n          >\n            <div\n              className=\"absolute inset-0\"\n              style={{\n                backdropFilter: \"blur(6px)\",\n                WebkitBackdropFilter: \"blur(6px)\",\n                clipPath: `path('${FLAP_PATH}')`,\n                WebkitClipPath: `path('${FLAP_PATH}')`,\n                transform: \"translateZ(0)\",\n                backfaceVisibility: \"hidden\",\n                WebkitBackfaceVisibility: \"hidden\",\n                willChange: \"transform\",\n              }}\n            />\n            <svg\n              className=\"absolute inset-0\"\n              width=\"321\"\n              height=\"241\"\n              viewBox=\"0 0 321 241\"\n              fill=\"none\"\n              xmlns=\"http://www.w3.org/2000/svg\"\n            >\n              <g filter=\"url(#filter0_i_171_13)\">\n                <path\n                  d={FLAP_PATH}\n                  fill={theme.flapFill}\n                  fillOpacity={theme.flapFillOpacity}\n                />\n                <path\n                  d=\"M25 0.5H136.084C142.905 0.5 149.417 3.3431 154.054 8.3457L177.713 33.874C182.539 39.0808 189.317 42.04 196.416 42.04H296C309.531 42.04 320.5 53.0092 320.5 66.54V216C320.5 229.531 309.531 240.5 296 240.5H25C11.469 240.5 0.5 229.531 0.5 216V25C0.5 11.469 11.469 0.5 25 0.5Z\"\n                  stroke={theme.flapStroke}\n                />\n              </g>\n              <defs>\n                <filter\n                  id=\"filter0_i_171_13\"\n                  x=\"-25.4\"\n                  y=\"-25.4\"\n                  width=\"371.8\"\n                  height=\"291.8\"\n                  filterUnits=\"userSpaceOnUse\"\n                  colorInterpolationFilters=\"sRGB\"\n                >\n                  <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\n                  <feBlend\n                    mode=\"normal\"\n                    in=\"SourceGraphic\"\n                    in2=\"BackgroundImageFix\"\n                    result=\"shape\"\n                  />\n                  <feColorMatrix\n                    in=\"SourceAlpha\"\n                    type=\"matrix\"\n                    values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\n                    result=\"hardAlpha\"\n                  />\n                  <feOffset />\n                  <feGaussianBlur stdDeviation=\"2.65\" />\n                  <feComposite\n                    in2=\"hardAlpha\"\n                    operator=\"arithmetic\"\n                    k2=\"-1\"\n                    k3=\"1\"\n                  />\n                  <feColorMatrix type=\"matrix\" values={theme.flapInsetColor} />\n                  <feBlend\n                    mode=\"normal\"\n                    in2=\"shape\"\n                    result=\"effect1_innerShadow_171_13\"\n                  />\n                </filter>\n              </defs>\n            </svg>\n          </motion.div>\n        </div>\n      </div>\n    </div>\n  );\n};\n\nexport default FolderComponent;\n\nexport { FolderComponent as Folder };\nexport type { FolderComponentProps };\n\ntype Theme = (typeof themes)[keyof typeof themes];\n\nconst Card = ({ id, theme }: { id: number; theme: Theme }) => {\n  const filterId = `filter0_i_card_${id}`;\n  return (\n    <div data-slot=\"folder-card\">\n      <svg\n        width=\"164\"\n        height=\"214\"\n        viewBox=\"0 0 164 214\"\n        fill=\"none\"\n        xmlns=\"http://www.w3.org/2000/svg\"\n      >\n        <g filter={`url(#${filterId})`}>\n          <rect\n            width=\"163.078\"\n            height=\"213.262\"\n            rx=\"20\"\n            fill={theme.cardFill}\n          />\n        </g>\n        <rect\n          x=\"0.5\"\n          y=\"0.5\"\n          width=\"162.078\"\n          height=\"212.262\"\n          rx=\"19.5\"\n          stroke={theme.cardStroke}\n        />\n        <rect\n          x=\"14.1193\"\n          y=\"31.2091\"\n          width=\"134.84\"\n          height=\"11.8892\"\n          rx=\"5.94459\"\n          fill={theme.cardLineFill}\n        />\n        <rect\n          width=\"64.5183\"\n          height=\"5.88276\"\n          rx=\"2.94138\"\n          transform=\"matrix(1 -0.000409158 0.00201956 0.999998 14.8253 60.9939)\"\n          fill={theme.cardLineFill}\n        />\n        <rect\n          width=\"64.5183\"\n          height=\"5.88276\"\n          rx=\"2.94138\"\n          transform=\"matrix(1 -0.000461045 0.00179228 0.999998 84.4303 60.9617)\"\n          fill={theme.cardLineFill}\n        />\n        <rect\n          width=\"64.5183\"\n          height=\"5.88276\"\n          rx=\"2.94138\"\n          transform=\"matrix(1 -0.000409158 0.00201956 0.999998 14.8253 75.1122)\"\n          fill={theme.cardLineFill}\n        />\n        <rect\n          width=\"64.5183\"\n          height=\"5.88276\"\n          rx=\"2.94138\"\n          transform=\"matrix(1 -0.000461045 0.00179228 0.999998 84.4303 75.0801)\"\n          fill={theme.cardLineFill}\n        />\n        <rect\n          width=\"64.5183\"\n          height=\"5.88276\"\n          rx=\"2.94138\"\n          transform=\"matrix(1 -0.000409158 0.00201956 0.999998 14.8253 89.2306)\"\n          fill={theme.cardLineFill}\n        />\n        <rect\n          width=\"64.5183\"\n          height=\"5.88276\"\n          rx=\"2.94138\"\n          transform=\"matrix(1 -0.000461045 0.00179228 0.999998 84.4303 89.1985)\"\n          fill={theme.cardLineFill}\n        />\n        <rect\n          width=\"64.5183\"\n          height=\"5.88276\"\n          rx=\"2.94138\"\n          transform=\"matrix(1 -0.000409158 0.00201956 0.999998 14.8253 103.349)\"\n          fill={theme.cardLineFill}\n        />\n        <rect\n          width=\"64.5183\"\n          height=\"5.88276\"\n          rx=\"2.94138\"\n          transform=\"matrix(1 -0.000461045 0.00179228 0.999998 84.4303 103.317)\"\n          fill={theme.cardLineFill}\n        />\n        <rect\n          width=\"64.5183\"\n          height=\"5.88276\"\n          rx=\"2.94138\"\n          transform=\"matrix(1 -0.000409158 0.00201956 0.999998 14.8253 117.467)\"\n          fill={theme.cardLineFill}\n        />\n        <rect\n          width=\"64.5183\"\n          height=\"5.88276\"\n          rx=\"2.94138\"\n          transform=\"matrix(1 -0.000461045 0.00179228 0.999998 84.4303 117.435)\"\n          fill={theme.cardLineFill}\n        />\n        <rect\n          width=\"64.5183\"\n          height=\"5.88276\"\n          rx=\"2.94138\"\n          transform=\"matrix(1 -0.000409158 0.00201956 0.999998 14.8253 131.586)\"\n          fill={theme.cardLineFill}\n        />\n        <rect\n          width=\"64.5183\"\n          height=\"5.88276\"\n          rx=\"2.94138\"\n          transform=\"matrix(1 -0.000461045 0.00179228 0.999998 84.4303 131.554)\"\n          fill={theme.cardLineFill}\n        />\n        <rect\n          width=\"64.5183\"\n          height=\"5.88276\"\n          rx=\"2.94138\"\n          transform=\"matrix(1 -0.000409158 0.00201956 0.999998 14.8253 145.704)\"\n          fill={theme.cardLineFill}\n        />\n        <rect\n          width=\"64.5183\"\n          height=\"5.88276\"\n          rx=\"2.94138\"\n          transform=\"matrix(1 -0.000461045 0.00179228 0.999998 84.4303 145.672)\"\n          fill={theme.cardLineFill}\n        />\n        <rect\n          width=\"64.5183\"\n          height=\"5.88276\"\n          rx=\"2.94138\"\n          transform=\"matrix(1 -0.000409158 0.00201956 0.999998 14.8253 159.823)\"\n          fill={theme.cardLineFill}\n        />\n        <rect\n          width=\"64.5183\"\n          height=\"5.88276\"\n          rx=\"2.94138\"\n          transform=\"matrix(1 -0.000461045 0.00179228 0.999998 84.4303 159.79)\"\n          fill={theme.cardLineFill}\n        />\n        <rect\n          width=\"64.5183\"\n          height=\"5.88276\"\n          rx=\"2.94138\"\n          transform=\"matrix(1 -0.000409158 0.00201956 0.999998 14.8253 173.941)\"\n          fill={theme.cardLineFill}\n        />\n        <rect\n          width=\"64.5183\"\n          height=\"5.88276\"\n          rx=\"2.94138\"\n          transform=\"matrix(1 -0.000461045 0.00179228 0.999998 84.4303 173.909)\"\n          fill={theme.cardLineFill}\n        />\n        <defs>\n          <filter\n            id={filterId}\n            x=\"0\"\n            y=\"0\"\n            width=\"166.078\"\n            height=\"218.262\"\n            filterUnits=\"userSpaceOnUse\"\n            colorInterpolationFilters=\"sRGB\"\n          >\n            <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\n            <feBlend\n              mode=\"normal\"\n              in=\"SourceGraphic\"\n              in2=\"BackgroundImageFix\"\n              result=\"shape\"\n            />\n            <feColorMatrix\n              in=\"SourceAlpha\"\n              type=\"matrix\"\n              values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\n              result=\"hardAlpha\"\n            />\n            <feMorphology\n              radius=\"2\"\n              operator=\"erode\"\n              in=\"SourceAlpha\"\n              result={`effect1_innerShadow_${id}`}\n            />\n            <feOffset dx=\"3\" dy=\"5\" />\n            <feGaussianBlur stdDeviation=\"3.05\" />\n            <feComposite in2=\"hardAlpha\" operator=\"arithmetic\" k2=\"-1\" k3=\"1\" />\n            <feColorMatrix type=\"matrix\" values={theme.cardInsetColor} />\n            <feBlend\n              mode=\"normal\"\n              in2=\"shape\"\n              result={`effect1_innerShadow_${id}`}\n            />\n          </filter>\n        </defs>\n      </svg>\n    </div>\n  );\n};\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}