"use client"; /** * Note: Use position fixed according to your needs * Desktop navbar is better positioned at the bottom * Mobile navbar is better positioned at bottom right. **/ import { cn } from "@/lib/utils"; import { IconLayoutNavbarCollapse } from "@tabler/icons-react"; import { AnimatePresence, MotionValue, motion, useMotionValue, useSpring, useTransform, } from "motion/react"; import { useRef, useState } from "react"; export const FloatingDock = ({ items, desktopClassName, mobileClassName, }: { items: { title: string; icon: React.ReactNode; href: string }[]; desktopClassName?: string; mobileClassName?: string; }) => { return ( <> ); }; const FloatingDockMobile = ({ items, className, }: { items: { title: string; icon: React.ReactNode; href: string }[]; className?: string; }) => { const [open, setOpen] = useState(false); return (
{open && ( {items.map((item, idx) => (
{item.icon}
))}
)}
); }; const FloatingDockDesktop = ({ items, className, }: { items: { title: string; icon: React.ReactNode; href: string }[]; className?: string; }) => { const mouseX = useMotionValue(Infinity); return ( mouseX.set(e.pageX)} onMouseLeave={() => mouseX.set(Infinity)} className={cn( "mx-auto hidden h-16 items-end gap-4 rounded-2xl bg-gray-50 px-4 pb-3 md:flex dark:bg-neutral-900", className )} > {items.map((item) => ( ))} ); }; function IconContainer({ mouseX, title, icon, href, }: { mouseX: MotionValue; title: string; icon: React.ReactNode; href: string; }) { const ref = useRef(null); const distance = useTransform(mouseX, (val) => { const bounds = ref.current?.getBoundingClientRect() ?? { x: 0, width: 0 }; return val - bounds.x - bounds.width / 2; }); const widthTransform = useTransform(distance, [-150, 0, 150], [40, 80, 40]); const heightTransform = useTransform(distance, [-150, 0, 150], [40, 80, 40]); const widthTransformIcon = useTransform(distance, [-150, 0, 150], [20, 40, 20]); const heightTransformIcon = useTransform(distance, [-150, 0, 150], [20, 40, 20]); const width = useSpring(widthTransform, { mass: 0.1, stiffness: 150, damping: 12, }); const height = useSpring(heightTransform, { mass: 0.1, stiffness: 150, damping: 12, }); const widthIcon = useSpring(widthTransformIcon, { mass: 0.1, stiffness: 150, damping: 12, }); const heightIcon = useSpring(heightTransformIcon, { mass: 0.1, stiffness: 150, damping: 12, }); const [hovered, setHovered] = useState(false); return ( setHovered(true)} onMouseLeave={() => setHovered(false)} className="relative flex aspect-square items-center justify-center rounded-full bg-gray-200 dark:bg-neutral-800" > {hovered && ( {title} )} {icon} ); }