{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "toggle-vault",
  "type": "registry:ui",
  "title": "Toggle Vault",
  "description": "Expandable vault component with animated open/close, trigger button, and content panel.",
  "author": "Ahdeetai <https://aditya.is-cool.dev>",
  "registryDependencies": [],
  "dependencies": ["motion"],
  "files": [
    {
      "type": "registry:ui",
      "path": "components/ui/toggle-vault.tsx",
      "content": "'use client';\nimport React, { useState, createContext, useContext, ReactNode } from 'react';\nimport { motion, AnimatePresence } from 'motion/react';\n\ninterface VaultContextType {\n  open: boolean;\n  toggleOpen: () => void;\n}\nconst VaultContext = createContext<VaultContextType | undefined>(undefined);\n\nexport interface ToggleVaultProps {\n  children: ReactNode;\n  className?: string;\n}\n\nexport const ToggleVault: React.FC<ToggleVaultProps> = ({\n  children,\n  className = '',\n}) => {\n  const [open, setOpen] = useState(false);\n  const toggleOpen = () => setOpen((prev) => !prev);\n\n  return (\n    <VaultContext.Provider value={{ open, toggleOpen }}>\n      <div className={`relative w-full h-full min-h-87.5 ${className}`}>\n        {children}\n      </div>\n    </VaultContext.Provider>\n  );\n};\n\ninterface TriggerProps {\n  children: ReactNode;\n  className?: string;\n}\nexport const ToggleVaultTrigger: React.FC<TriggerProps> = ({\n  children,\n  className = '',\n}) => {\n  const context = useContext(VaultContext);\n  if (!context)\n    throw new Error('ToggleVaultTrigger must be inside ToggleVault');\n  const { open, toggleOpen } = context;\n\n  if (open) return null;\n\n  return (\n    <motion.div\n      onClick={toggleOpen}\n      aria-expanded={open}\n      className={`\n        absolute top-4 right-4 w-25 h-10 rounded-full flex items-center justify-center\n        cursor-pointer z-50 transition-all duration-300 hover:scale-105 shadow-lg\n        bg-black text-white dark:bg-white dark:text-black\n        ${className}\n      `}\n    >\n      <motion.span\n        initial={{ y: -10, opacity: 0 }}\n        animate={{ y: 0, opacity: 1 }}\n        exit={{ y: 10, opacity: 0 }}\n        className='font-bold'\n      >\n        {children}\n      </motion.span>\n    </motion.div>\n  );\n};\n\ninterface CloseProps {\n  children: ReactNode;\n  className?: string;\n}\nexport const ToggleVaultClose: React.FC<CloseProps> = ({\n  children,\n  className = '',\n}) => {\n  const context = useContext(VaultContext);\n  if (!context) throw new Error('ToggleVaultClose must be inside ToggleVault');\n  const { open, toggleOpen } = context;\n  if (!open) return null;\n\n  return (\n    <motion.div\n      onClick={toggleOpen}\n      key='close'\n      initial={{ y: 10, opacity: 0 }}\n      animate={{ y: 0, opacity: 1 }}\n      exit={{ y: -10, opacity: 0 }}\n      className={`\n        absolute top-4 right-4 w-25 h-10 rounded-full flex items-center justify-center\n        z-50 font-bold cursor-pointer transition-all duration-300 hover:scale-105 shadow-lg\n        bg-white text-black dark:bg-black dark:text-white\n        ${className}\n      `}\n    >\n      {children}\n    </motion.div>\n  );\n};\n\ninterface ContentProps {\n  children: ReactNode;\n  className?: string;\n}\nexport const ToggleVaultContent: React.FC<ContentProps> = ({\n  children,\n  className = '',\n}) => {\n  const context = useContext(VaultContext);\n  if (!context)\n    throw new Error('ToggleVaultContent must be inside ToggleVault');\n  const { open, toggleOpen } = context;\n\n  return (\n    <AnimatePresence>\n      {open && (\n        <motion.div\n          key='panel'\n          initial={{\n            scaleX: 0.2,\n            scaleY: 0.066,\n            top: '1rem',\n            right: '1rem',\n            opacity: 0,\n          }}\n          animate={{\n            scaleX: 1,\n            scaleY: 1,\n            top: '0.6rem',\n            right: '0.6rem',\n            opacity: 1,\n            transition: { duration: 0.7, ease: [0.2, 0.9, 0.3, 1] },\n          }}\n          exit={{\n            scaleX: 0.2,\n            scaleY: 0.066,\n            top: '1rem',\n            right: '1rem',\n            opacity: 0,\n            transition: { duration: 0.6, ease: [0.2, 0.9, 0.3, 1] },\n          }}\n          className={`\n            absolute rounded-2xl overflow-hidden z-40 shadow-lg \n            bg-black text-white dark:bg-white dark:text-black\n            ${className}\n          `}\n          style={{ transformOrigin: 'top right' }}\n          aria-hidden={!open}\n        >\n          <motion.div\n            initial={{ opacity: 0 }}\n            animate={{ opacity: 1, transition: { delay: 0.4 } }}\n            exit={{ opacity: 0 }}\n            className='p-1 flex flex-col gap-3 font-bold font-bricolage'\n          >\n            {children}\n          </motion.div>\n        </motion.div>\n      )}\n    </AnimatePresence>\n  );\n};\n"
    }
  ]
}
