{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "expandable-screen",
  "type": "registry:ui",
  "description": "A full-screen expandable component with morphing animations using shared layout IDs for smooth transitions",
  "dependencies": [
    "motion",
    "lucide-react"
  ],
  "files": [
    {
      "path": "registry/default/ui/expandable-screen.tsx",
      "content": "\"use client\"\n\nimport {\n  createContext,\n  useContext,\n  useEffect,\n  useState,\n  type ReactNode,\n} from \"react\"\nimport { X } from \"lucide-react\"\nimport { AnimatePresence, motion } from \"motion/react\"\n\n// Context\ninterface ExpandableScreenContextValue {\n  isExpanded: boolean\n  expand: () => void\n  collapse: () => void\n  layoutId: string\n  triggerRadius: string\n  contentRadius: string\n  animationDuration: number\n}\n\nconst ExpandableScreenContext =\n  createContext<ExpandableScreenContextValue | null>(null)\n\nfunction useExpandableScreen() {\n  const context = useContext(ExpandableScreenContext)\n  if (!context) {\n    throw new Error(\n      \"useExpandableScreen must be used within an ExpandableScreen\"\n    )\n  }\n  return context\n}\n\n// Root Component\ninterface ExpandableScreenProps {\n  children: ReactNode\n  defaultExpanded?: boolean\n  onExpandChange?: (expanded: boolean) => void\n  layoutId?: string\n  triggerRadius?: string\n  contentRadius?: string\n  animationDuration?: number\n  lockScroll?: boolean\n}\n\nexport function ExpandableScreen({\n  children,\n  defaultExpanded = false,\n  onExpandChange,\n  layoutId = \"expandable-card\",\n  triggerRadius = \"100px\",\n  contentRadius = \"24px\",\n  animationDuration = 0.3,\n  lockScroll = true,\n}: ExpandableScreenProps) {\n  const [isExpanded, setIsExpanded] = useState(defaultExpanded)\n\n  const expand = () => {\n    setIsExpanded(true)\n    onExpandChange?.(true)\n  }\n\n  const collapse = () => {\n    setIsExpanded(false)\n    onExpandChange?.(false)\n  }\n\n  useEffect(() => {\n    if (lockScroll) {\n      if (isExpanded) {\n        document.body.style.overflow = \"hidden\"\n      } else {\n        document.body.style.overflow = \"unset\"\n      }\n    }\n  }, [isExpanded, lockScroll])\n\n  return (\n    <ExpandableScreenContext.Provider\n      value={{\n        isExpanded,\n        expand,\n        collapse,\n        layoutId,\n        triggerRadius,\n        contentRadius,\n        animationDuration,\n      }}\n    >\n      {children}\n    </ExpandableScreenContext.Provider>\n  )\n}\n\n// Trigger Component\ninterface ExpandableScreenTriggerProps {\n  children: ReactNode\n  className?: string\n}\n\nexport function ExpandableScreenTrigger({\n  children,\n  className = \"\",\n}: ExpandableScreenTriggerProps) {\n  const { isExpanded, expand, layoutId, triggerRadius } = useExpandableScreen()\n\n  return (\n    <AnimatePresence initial={false}>\n      {!isExpanded && (\n        <motion.div className={`relative inline-block ${className}`}>\n          {/* Background layer with shared layoutId for morphing */}\n          <motion.div\n            style={{\n              borderRadius: triggerRadius,\n            }}\n            layout\n            layoutId={layoutId}\n            className=\"absolute inset-0 transform-gpu will-change-transform\"\n          />\n          {/* Content layer that fades out on expand */}\n          <motion.div\n            initial={{ opacity: 0, scale: 0.8 }}\n            animate={{ opacity: 1, scale: 1 }}\n            transition={{ delay: 0.2 }}\n            exit={{ opacity: 0, scale: 0.8 }}\n            layout={false}\n            onClick={expand}\n            className=\"relative cursor-pointer\"\n          >\n            {children}\n          </motion.div>\n        </motion.div>\n      )}\n    </AnimatePresence>\n  )\n}\n\n// Content Component\ninterface ExpandableScreenContentProps {\n  children: ReactNode\n  className?: string\n  showCloseButton?: boolean\n  closeButtonClassName?: string\n}\n\nexport function ExpandableScreenContent({\n  children,\n  className = \"\",\n  showCloseButton = true,\n  closeButtonClassName = \"\",\n}: ExpandableScreenContentProps) {\n  const { isExpanded, collapse, layoutId, contentRadius, animationDuration } =\n    useExpandableScreen()\n\n  return (\n    <AnimatePresence initial={false}>\n      {isExpanded && (\n        <div className=\"fixed inset-0 z-50 flex items-center justify-center p-3 sm:p-2\">\n          {/* Morphing background with shared layoutId */}\n          <motion.div\n            layoutId={layoutId}\n            transition={{ duration: animationDuration }}\n            style={{\n              borderRadius: contentRadius,\n            }}\n            layout\n            className={`relative flex h-full w-full transform-gpu overflow-y-auto will-change-transform ${className}`}\n          >\n            <motion.div\n              initial={{ opacity: 0 }}\n              animate={{ opacity: 1 }}\n              transition={{ delay: 0.15, duration: 0.4 }}\n              className=\"relative z-20 w-full\"\n            >\n              {children}\n            </motion.div>\n\n            {showCloseButton && (\n              <motion.button\n                onClick={collapse}\n                className={`absolute top-6 right-6 z-30 flex h-10 w-10 items-center justify-center rounded-full transition-colors ${\n                  closeButtonClassName ||\n                  \"text-primary-foreground hover:bg-primary-foreground/10 bg-transparent\"\n                }`}\n                aria-label=\"Close\"\n              >\n                <X className=\"h-5 w-5\" />\n              </motion.button>\n            )}\n          </motion.div>\n        </div>\n      )}\n    </AnimatePresence>\n  )\n}\n\n// Background Component (optional)\ninterface ExpandableScreenBackgroundProps {\n  trigger?: ReactNode\n  content?: ReactNode\n  className?: string\n}\n\nexport function ExpandableScreenBackground({\n  trigger,\n  content,\n  className = \"\",\n}: ExpandableScreenBackgroundProps) {\n  const { isExpanded } = useExpandableScreen()\n\n  if (isExpanded && content) {\n    return <div className={className}>{content}</div>\n  }\n\n  if (!isExpanded && trigger) {\n    return <div className={className}>{trigger}</div>\n  }\n\n  return null\n}\n\nexport { useExpandableScreen }\n",
      "type": "registry:ui"
    }
  ]
}