{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "floating-dock", "title": "Floating Dock", "description": "A floating dock component with a list of items. | アイテムリストを備えたフローティングドックコンポーネント。", "dependencies": [ "lucide-react", "motion", "tabler-icons" ], "files": [ { "path": "components/navigation/floating-dock.tsx", "content": "\"use client\";\n/**\n * Note: Use position fixed according to your needs\n * Desktop navbar is better positioned at the bottom\n * Mobile navbar is better positioned at bottom right.\n **/\n\nimport { useRef, useState } from \"react\";\nimport {\n AnimatePresence,\n MotionValue,\n motion,\n useMotionValue,\n useSpring,\n useTransform,\n} from \"motion/react\";\nimport { IconLayoutNavbarCollapse } from \"@tabler/icons-react\";\nimport { cn } from \"@/lib/utils\";\n\nexport const FloatingDock = ({\n items,\n desktopClassName,\n mobileClassName,\n}: {\n items: { title: string; icon: React.ReactNode; href: string }[];\n desktopClassName?: string;\n mobileClassName?: string;\n}) => {\n return (\n <>\n \n \n \n );\n};\n\nconst FloatingDockMobile = ({\n items,\n className,\n}: {\n items: { title: string; icon: React.ReactNode; href: string }[];\n className?: string;\n}) => {\n const [open, setOpen] = useState(false);\n return (\n
\n \n {open && (\n \n {items.map((item, idx) => (\n \n \n
{item.icon}
\n \n \n ))}\n \n )}\n
\n setOpen(!open)}\n className=\"flex size-10 items-center justify-center rounded-full bg-neutral-50 dark:bg-neutral-800\"\n >\n \n \n
\n );\n};\n\nconst FloatingDockDesktop = ({\n items,\n className,\n}: {\n items: { title: string; icon: React.ReactNode; href: string }[];\n className?: string;\n}) => {\n let mouseX = useMotionValue(Infinity);\n return (\n mouseX.set(e.pageX)}\n onMouseLeave={() => mouseX.set(Infinity)}\n className={cn(\n \"mx-auto hidden h-16 items-end gap-4 rounded-2xl bg-neutral-50 px-4 pb-3 md:flex dark:bg-neutral-900\",\n className,\n )}\n >\n {items.map((item) => (\n \n ))}\n \n );\n};\n\nfunction IconContainer({\n mouseX,\n title,\n icon,\n href,\n}: {\n mouseX: MotionValue;\n title: string;\n icon: React.ReactNode;\n href: string;\n}) {\n let ref = useRef(null);\n\n let distance = useTransform(mouseX, (val) => {\n let bounds = ref.current?.getBoundingClientRect() ?? { x: 0, width: 0 };\n\n return val - bounds.x - bounds.width / 2;\n });\n\n let widthTransform = useTransform(distance, [-150, 0, 150], [40, 80, 40]);\n let heightTransform = useTransform(distance, [-150, 0, 150], [40, 80, 40]);\n\n let widthTransformIcon = useTransform(distance, [-150, 0, 150], [20, 40, 20]);\n let heightTransformIcon = useTransform(\n distance,\n [-150, 0, 150],\n [20, 40, 20],\n );\n\n let width = useSpring(widthTransform, {\n mass: 0.1,\n stiffness: 150,\n damping: 12,\n });\n let height = useSpring(heightTransform, {\n mass: 0.1,\n stiffness: 150,\n damping: 12,\n });\n\n let widthIcon = useSpring(widthTransformIcon, {\n mass: 0.1,\n stiffness: 150,\n damping: 12,\n });\n let heightIcon = useSpring(heightTransformIcon, {\n mass: 0.1,\n stiffness: 150,\n damping: 12,\n });\n\n const [hovered, setHovered] = useState(false);\n\n return (\n \n setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n className=\"relative flex aspect-square items-center justify-center rounded-full bg-neutral-200 dark:bg-neutral-800\"\n >\n \n {hovered && (\n \n {title}\n \n )}\n \n \n {icon}\n \n \n \n );\n}\n", "type": "registry:ui" } ], "type": "registry:ui" }