{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "floating-nav",
  "type": "registry:component",
  "title": "Floating nav",
  "description": "A sticky marketing navbar that tucks into a floating pill after you scroll, with a hover highlight that glides between links and an animated mobile menu.",
  "dependencies": [
    "lucide-react",
    "motion"
  ],
  "registryDependencies": [
    "https://ui.minidev.pro/r/button.json",
    "utils"
  ],
  "files": [
    {
      "path": "registry/blocks/floating-nav.tsx",
      "type": "registry:ui",
      "target": "components/ui/floating-nav.tsx",
      "content": "\"use client\"\nimport * as React from \"react\"\nimport { AnimatePresence, motion, useMotionValueEvent, useReducedMotion, useScroll } from \"motion/react\"\nimport { MenuIcon, XIcon } from \"lucide-react\"\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\n\n/*\n * FloatingNav: a full-width bar at the top that, once you scroll, tucks into\n * a floating pill with a raised surface. Hover highlight glides between\n * links on one shared element. Mobile gets a sheet that drops from the pill.\n */\n\ntype NavLink = { label: string; href: string }\n\ntype FloatingNavProps = {\n  brand?: React.ReactNode\n  links?: NavLink[]\n  cta?: { label: string; href?: string; onClick?: () => void }\n  secondary?: { label: string; href?: string } | null\n  /** Sticky inside a scroll container instead of the viewport. */\n  className?: string\n}\n\nconst LINKS: NavLink[] = [\n  { label: \"Product\", href: \"#product\" },\n  { label: \"How it works\", href: \"#how\" },\n  { label: \"Customers\", href: \"#customers\" },\n  { label: \"Pricing\", href: \"#pricing\" },\n  { label: \"FAQ\", href: \"#faq\" },\n]\n\nfunction FloatingNav({\n  brand = (\n    <span className=\"flex items-center gap-2 text-[15px] font-semibold tracking-[-0.02em] text-fg\">\n      <span className=\"grid size-7 place-items-center rounded-lg bg-ink text-[13px] text-on-ink shadow-ink\">L</span>\n      Lumen\n    </span>\n  ),\n  links = LINKS,\n  cta = { label: \"Start free\" },\n  secondary = { label: \"Sign in\", href: \"#\" },\n  className,\n}: FloatingNavProps) {\n  const { scrollY } = useScroll()\n  const [tucked, setTucked] = React.useState(false)\n  const [hover, setHover] = React.useState<string | null>(null)\n  const [open, setOpen] = React.useState(false)\n  const reduce = useReducedMotion()\n  const id = React.useId()\n  useMotionValueEvent(scrollY, \"change\", (y) => setTucked(y > 40))\n  const spring = reduce ? { duration: 0 } : { type: \"spring\" as const, bounce: 0.16, duration: 0.5 }\n\n  return (\n    <div data-slot=\"floating-nav\" className={cn(\"sticky top-0 z-50 px-3 pt-3\", className)}>\n      <motion.nav\n        layout\n        transition={spring}\n        aria-label=\"Main\"\n        className={cn(\n          \"mx-auto flex h-14 items-center gap-2 pr-2 pl-4\",\n          tucked ? \"max-w-4xl rounded-2xl border border-border bg-raised shadow-overlay\" : \"max-w-7xl rounded-2xl border border-transparent\"\n        )}\n      >\n        <a href=\"#\" className=\"mr-3 shrink-0 rounded-md outline-none focus-visible:ring-2 focus-visible:ring-accent\">\n          {brand}\n        </a>\n        <ul className=\"hidden flex-1 items-center md:flex\" onMouseLeave={() => setHover(null)}>\n          {links.map((l) => (\n            <li key={l.href}>\n              <a\n                href={l.href}\n                onMouseEnter={() => setHover(l.href)}\n                onFocus={() => setHover(l.href)}\n                className=\"relative block rounded-lg px-3 py-1.5 text-[13.5px] text-fg-muted outline-none transition-colors duration-[70ms] hover:text-fg focus-visible:text-fg\"\n              >\n                {hover === l.href ? (\n                  <motion.span layoutId={`${id}-hl`} transition={spring} aria-hidden className=\"absolute inset-0 -z-10 rounded-lg bg-fg/[0.05]\" />\n                ) : null}\n                {l.label}\n              </a>\n            </li>\n          ))}\n        </ul>\n        <div className=\"ml-auto flex items-center gap-1.5\">\n          {secondary ? (\n            <Button variant=\"ghost\" size=\"sm\" className=\"hidden sm:inline-flex\" render={secondary.href ? <a href={secondary.href} /> : undefined}>\n              {secondary.label}\n            </Button>\n          ) : null}\n          {cta ? (\n            <Button size=\"sm\" onClick={cta.onClick} render={cta.href ? <a href={cta.href} /> : undefined}>\n              {cta.label}\n            </Button>\n          ) : null}\n          <Button variant=\"ghost\" size=\"icon-sm\" className=\"md:hidden\" aria-label={open ? \"Close menu\" : \"Open menu\"} aria-expanded={open} onClick={() => setOpen((o) => !o)}>\n            {open ? <XIcon /> : <MenuIcon />}\n          </Button>\n        </div>\n      </motion.nav>\n      <AnimatePresence>\n        {open ? (\n          <motion.div\n            initial={{ opacity: 0, y: -8, scale: 0.98 }}\n            animate={{ opacity: 1, y: 0, scale: 1 }}\n            exit={{ opacity: 0, y: -6, scale: 0.99, transition: { duration: 0.14 } }}\n            transition={spring}\n            className=\"mx-auto mt-2 max-w-4xl origin-top rounded-2xl border border-border bg-raised p-2 shadow-overlay md:hidden\"\n          >\n            {links.map((l) => (\n              <a key={l.href} href={l.href} onClick={() => setOpen(false)} className=\"block rounded-lg px-3 py-3 text-[15px] text-fg outline-none hover:bg-sunken focus-visible:bg-sunken\">\n                {l.label}\n              </a>\n            ))}\n          </motion.div>\n        ) : null}\n      </AnimatePresence>\n    </div>\n  )\n}\n\nexport { FloatingNav }\nexport type { FloatingNavProps, NavLink }\n"
    }
  ]
}
