{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "native-morphing-button-carbon",
  "type": "registry:component",
  "title": "Native Morphing Button",
  "description": "Floating action button that morphs into a menu of actions.",
  "dependencies": [
    "framer-motion",
    "react"
  ],
  "files": [
    {
      "path": "@uitripled/react-carbon/src/components/native/native-morphing-button-carbon.tsx",
      "content": "\"use client\";\n\nimport { cn } from \"@/lib/utils\";\nimport {\n  AnimatePresence,\n  LayoutGroup,\n  motion,\n  Transition,\n  useReducedMotion,\n} from \"framer-motion\";\nimport { Plus, X } from \"lucide-react\";\nimport { useState } from \"react\";\n\nexport interface MorphingButtonAction {\n  /**\n   * Display label for the action.\n   */\n  label: string;\n  /**\n   * Icon to display alongside the label.\n   */\n  icon: React.ReactNode;\n  /**\n   * Callback when action is clicked.\n   */\n  onClick: () => void;\n}\n\nexport interface NativeMorphingButtonProps {\n  /**\n   * Array of actions to display in the expanded menu.\n   */\n  actions: MorphingButtonAction[];\n  /**\n   * Position of the FAB.\n   * Default: 'bottom-right'\n   */\n  position?: \"bottom-right\" | \"bottom-left\" | \"top-right\" | \"top-left\";\n  /**\n   * Whether to use fixed positioning.\n   * Default: false (relative to container)\n   */\n  fixed?: boolean;\n  /**\n   * Custom icon when collapsed.\n   */\n  icon?: React.ReactNode;\n  /**\n   * Custom close icon when expanded.\n   */\n  closeIcon?: React.ReactNode;\n  className?: string;\n}\n\nconst positionClasses = {\n  \"bottom-right\": \"bottom-4 right-4\",\n  \"bottom-left\": \"bottom-4 left-4\",\n  \"top-right\": \"top-4 right-4\",\n  \"top-left\": \"top-4 left-4\",\n};\n\nconst springTransition: Transition = {\n  type: \"spring\",\n  stiffness: 300,\n  damping: 30,\n};\nconst reducedTransition: Transition = { duration: 0.1 };\n\nexport function NativeMorphingButton({\n  actions,\n  position = \"bottom-right\",\n  fixed = false,\n  icon,\n  closeIcon,\n  className,\n}: NativeMorphingButtonProps) {\n  const [isExpanded, setIsExpanded] = useState(false);\n  const shouldReduceMotion = useReducedMotion();\n\n  const transition = shouldReduceMotion ? reducedTransition : springTransition;\n\n  return (\n    <div\n      className={cn(\n        fixed ? \"fixed\" : \"absolute\",\n        positionClasses[position],\n        \"z-50\",\n        className\n      )}\n    >\n      <LayoutGroup>\n        <motion.div\n          layout\n          className=\"relative\"\n          initial={false}\n          animate={{\n            width: isExpanded ? 280 : 56,\n            height: isExpanded ? \"auto\" : 56,\n            borderRadius: isExpanded ? 16 : 28,\n          }}\n          transition={transition}\n        >\n          {/* Main FAB Button */}\n          <motion.button\n            onClick={() => setIsExpanded(!isExpanded)}\n            className=\"absolute right-0 bottom-0 flex h-14 w-14 items-center justify-center rounded-full bg-primary text-primary-foreground shadow-lg transition-shadow hover:shadow-xl focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2\"\n            whileHover={shouldReduceMotion ? undefined : { scale: 1.05 }}\n            whileTap={shouldReduceMotion ? undefined : { scale: 0.95 }}\n            aria-label={isExpanded ? \"Close menu\" : \"Open menu\"}\n            aria-expanded={isExpanded}\n          >\n            <AnimatePresence mode=\"wait\">\n              {isExpanded ? (\n                <motion.div\n                  key=\"close\"\n                  initial={\n                    shouldReduceMotion ? false : { rotate: -90, opacity: 0 }\n                  }\n                  animate={{ rotate: 0, opacity: 1 }}\n                  exit={{ rotate: 90, opacity: 0 }}\n                  transition={{ duration: 0.2 }}\n                >\n                  {closeIcon ?? <X className=\"h-5 w-5\" />}\n                </motion.div>\n              ) : (\n                <motion.div\n                  key=\"open\"\n                  initial={\n                    shouldReduceMotion ? false : { rotate: 90, opacity: 0 }\n                  }\n                  animate={{ rotate: 0, opacity: 1 }}\n                  exit={{ rotate: -90, opacity: 0 }}\n                  transition={{ duration: 0.2 }}\n                >\n                  {icon ?? <Plus className=\"h-5 w-5\" />}\n                </motion.div>\n              )}\n            </AnimatePresence>\n          </motion.button>\n\n          {/* Expanded Menu */}\n          <AnimatePresence>\n            {isExpanded && (\n              <motion.div\n                initial={\n                  shouldReduceMotion\n                    ? { opacity: 0 }\n                    : { opacity: 0, scale: 0.8 }\n                }\n                animate={{ opacity: 1, scale: 1 }}\n                exit={{ opacity: 0, scale: 0.8 }}\n                transition={{ duration: 0.2, delay: 0.1 }}\n                className=\"absolute bottom-0 right-0 w-64 rounded-2xl border border-border bg-card p-4 shadow-2xl\"\n                role=\"menu\"\n              >\n                <div className=\"mb-2 space-y-2\">\n                  {actions.map((action, index) => (\n                    <motion.button\n                      key={action.label}\n                      initial={\n                        shouldReduceMotion ? false : { opacity: 0, x: -20 }\n                      }\n                      animate={{ opacity: 1, x: 0 }}\n                      transition={{ delay: index * 0.05 + 0.2 }}\n                      onClick={() => {\n                        action.onClick();\n                        setIsExpanded(false);\n                      }}\n                      className=\"flex w-full items-center gap-3 rounded-lg px-4 py-3 text-left text-sm transition-colors hover:bg-muted focus:outline-none focus:ring-2 focus:ring-ring\"\n                      role=\"menuitem\"\n                    >\n                      <span className=\"text-muted-foreground\">\n                        {action.icon}\n                      </span>\n                      <span className=\"font-medium\">{action.label}</span>\n                    </motion.button>\n                  ))}\n                </div>\n              </motion.div>\n            )}\n          </AnimatePresence>\n        </motion.div>\n      </LayoutGroup>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/uitripled/native-morphing-button-carbon.tsx"
    }
  ]
}