"use client"; import { useId, useState, type MouseEvent, type RefObject } from "react"; import { motion, useMotionValueEvent, useReducedMotion, useScroll } from "motion/react"; export type FloatNavItem = { label: string; href: string }; type FloatNavProps = { items: FloatNavItem[]; /** href of the active link at start. Defaults to the first item. */ active?: string; /** Called on click. Call e.preventDefault() to stop the browser following the link. */ onSelect?: (item: FloatNavItem, e: MouseEvent) => void; /** Slip away while scrolling down, come back on scroll up. */ hideOnScroll?: boolean; /** Scrolling box to watch. Leave out to watch the page. */ container?: RefObject; /** Colour of the sliding pill. */ color?: string; /** Text colour on the pill. */ activeText?: string; /** Name read out by screen readers. */ label?: string; className?: string; }; /* FloatNav: a floating pill bar. The active pill slides between links; the bar slips away on scroll down. */ export function FloatNav({ items, active, onSelect, hideOnScroll = true, container, color = "#a78bfa", activeText = "#0b0a14", label = "Main", className = "rounded-full border border-white/10 bg-[#16132a]/80 p-1.5 text-sm text-white/70 shadow-lg shadow-black/40 backdrop-blur-md", }: FloatNavProps) { const reduce = useReducedMotion(); const id = useId(); const [current, setCurrent] = useState(active ?? items[0]?.href); const [hidden, setHidden] = useState(false); const { scrollY } = useScroll({ container }); useMotionValueEvent(scrollY, "change", (y) => { if (!hideOnScroll) return; const prev = scrollY.getPrevious() ?? 0; setHidden(y > prev && y > 80); }); const spring = reduce ? { duration: 0 } : { type: "spring" as const, stiffness: 420, damping: 34 }; return ( setHidden(false)} animate={{ y: hidden ? "-160%" : "0%", opacity: hidden ? 0 : 1 }} transition={spring} className={`inline-flex ${className}`} > ); }