{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "floating-button",
  "type": "registry:component",
  "title": "Floating Button",
  "author": "Toby Belhome",
  "description": "Use these Tailwind CSS hero section examples to showcase messaging, product images, and calls-to-action at the top of your site, featuring various styles and layouts.",
  "dependencies": [
    "motion",
    "usehooks-ts",
    "lucide-react"
  ],
  "registryDependencies": [
    "button",
    "http://localhost:3000/r/floating-button.json"
  ],
  "files": [
    {
      "path": "examples/motion/components/floating-button/01/floating-button.tsx",
      "content": "\"use client\";\n\nimport React, { ReactNode } from \"react\";\nimport { AnimatePresence, motion } from \"motion/react\";\nimport { useOnClickOutside } from \"usehooks-ts\";\n\ntype FloatingButtonProps = {\n  className?: string;\n  children: ReactNode;\n  triggerContent: ReactNode;\n};\n\ntype FloatingButtonItemProps = {\n  children: ReactNode;\n};\n\nconst list = {\n  visible: {\n    opacity: 1,\n    transition: {\n      staggerChildren: 0.1,\n      staggerDirection: -1\n    }\n  },\n  hidden: {\n    opacity: 0,\n    transition: {\n      when: \"afterChildren\",\n      staggerChildren: 0.1\n    }\n  }\n};\n\nconst item = {\n  visible: { opacity: 1, y: 0 },\n  hidden: { opacity: 0, y: 5 }\n};\n\nconst btn = {\n  visible: { rotate: \"45deg\" },\n  hidden: { rotate: 0 }\n};\n\nfunction FloatingButton({ children, triggerContent }: FloatingButtonProps) {\n  const ref = React.useRef<HTMLDivElement | null>(null);\n  const [isOpen, setIsOpen] = React.useState(false);\n\n  useOnClickOutside(ref as React.RefObject<HTMLDivElement>, () => setIsOpen(false));\n\n  return (\n    <div className=\"relative flex flex-col items-center\">\n      <AnimatePresence>\n        <motion.ul\n          key=\"list\"\n          className=\"absolute bottom-14 flex flex-col items-center gap-2\"\n          initial=\"hidden\"\n          animate={isOpen ? \"visible\" : \"hidden\"}\n          variants={list}>\n          {children}\n        </motion.ul>\n        <motion.div\n          key=\"button\"\n          variants={btn}\n          animate={isOpen ? \"visible\" : \"hidden\"}\n          ref={ref}\n          onClick={() => setIsOpen(!isOpen)}\n          className=\"cursor-pointer\">\n          {triggerContent}\n        </motion.div>\n      </AnimatePresence>\n    </div>\n  );\n}\n\nfunction FloatingButtonItem({ children }: FloatingButtonItemProps) {\n  return <motion.li variants={item}>{children}</motion.li>;\n}\n\nexport { FloatingButton, FloatingButtonItem };\n",
      "type": "registry:component",
      "target": "components/floating-button/floating-button.tsx"
    },
    {
      "path": "examples/motion/components/floating-button/01/page.tsx",
      "content": "import { cn } from \"@/lib/utils\";\nimport { DribbbleIcon, FacebookIcon, LinkedinIcon, PlusIcon } from \"lucide-react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { FloatingButton, FloatingButtonItem } from \"./floating-button\";\n\nexport default function FloatingButtonExample() {\n  const items = [\n    {\n      id: \"facebook\",\n      icon: <FacebookIcon />,\n      bgColor: \"bg-[#1877f2]\"\n    },\n    {\n      id: \"dribbble\",\n      icon: <DribbbleIcon />,\n      bgColor: \"bg-[#ea4c89]\"\n    },\n    {\n      id: \"linkedin\",\n      icon: <LinkedinIcon />,\n      bgColor: \"bg-[#0a66c2]\"\n    }\n  ];\n\n  return (\n    <FloatingButton\n      triggerContent={\n        <Button size=\"icon\" className=\"size-12 rounded-full\">\n          <PlusIcon className=\"size-5\" />\n        </Button>\n      }>\n      {items.map((item) => (\n        <FloatingButtonItem key={item.id}>\n          <Button size=\"icon\" className={cn(\"size-12 rounded-full\", item.bgColor)}>\n            {item.icon}\n          </Button>\n        </FloatingButtonItem>\n      ))}\n    </FloatingButton>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/floating-button/floating-button-example.tsx"
    }
  ],
  "meta": {
    "isPro": false
  }
}