{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "glass-nav",
  "title": "Glass Nav",
  "author": "Alex Chih (https://alexchih.com)",
  "description": "Floating glass pill navigation — sliding hover pill, scroll-adaptive contrast, masked blur scroll edge, working mobile sheet.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "https://washiveil.alexchih.com/r/theme.json"
  ],
  "files": [
    {
      "path": "registry/washiveil/ui/glass-nav.tsx",
      "content": "'use client';\n\nimport { useEffect, useId, useRef, useState } from 'react';\nimport { cn } from '@/lib/utils';\n\ninterface GlassNavProps {\n  brand: React.ReactNode;\n  links: { label: string; href: string }[];\n  activeHref?: string;\n  cta?: { label: string; href: string };\n  children?: React.ReactNode;\n  className?: string;\n}\n\nexport function GlassNav({ brand, links, activeHref, cta, children, className }: GlassNavProps) {\n  const headerRef = useRef<HTMLElement>(null);\n  const pillRef = useRef<HTMLSpanElement>(null);\n  const [open, setOpen] = useState(false);\n  const panelId = useId();\n\n  useEffect(() => {\n    const hdr = headerRef.current;\n    if (!hdr) return;\n    const sync = () => hdr.toggleAttribute('data-scrolled', window.scrollY > 24);\n    window.addEventListener('scroll', sync, { passive: true });\n    sync();\n    return () => window.removeEventListener('scroll', sync);\n  }, []);\n\n  const handleItemEnter = (e: React.MouseEvent<HTMLAnchorElement>) => {\n    const el = e.currentTarget;\n    const pill = pillRef.current;\n    if (!pill) return;\n    pill.style.width = `${el.offsetWidth}px`;\n    pill.style.height = `${el.offsetHeight}px`;\n    pill.style.transform = `translate(${el.offsetLeft}px, ${el.offsetTop}px)`;\n    pill.style.opacity = '1';\n  };\n\n  const handleNavLeave = () => {\n    if (pillRef.current) pillRef.current.style.opacity = '0';\n  };\n\n  const activeClass = 'bg-ruri font-medium text-white dark:bg-ruri-soft dark:text-deep';\n  const inactiveClass = 'text-muted-foreground hover:text-foreground';\n\n  return (\n    <header\n      ref={headerRef}\n      className={cn('group sticky top-4 z-30 mt-4', className)}\n      style={{ viewTransitionName: 'site-nav' }}\n    >\n      {/* Scroll-edge masked backdrop-blur band */}\n      <div\n        className=\"pointer-events-none absolute inset-x-0 -top-4 -z-10 h-[calc(100%+2.5rem)] backdrop-blur-md [mask-image:linear-gradient(to_bottom,black_45%,transparent)]\"\n        aria-hidden=\"true\"\n      />\n\n      {/* Glass pill */}\n      <div className=\"veil-grain grid grid-cols-[1fr_auto] items-center rounded-full lg:grid-cols-[1fr_auto_1fr] border border-glass-edge bg-glass-strong px-5 py-3 shadow-[inset_0_1px_0_rgba(255,255,255,0.70),inset_0_-1px_0_rgba(28,25,20,0.05),0_8px_32px_rgba(28,25,20,0.08)] backdrop-blur-2xl backdrop-saturate-150 transition-colors duration-300 group-data-[scrolled]:bg-glass-stronger sm:px-6 dark:shadow-[inset_0_1px_0_rgba(255,255,255,0.10),inset_0_-1px_0_rgba(0,0,0,0.35),0_8px_32px_rgba(0,0,0,0.35)]\">\n        {/* Brand zone */}\n        {brand}\n\n        {/* Desktop nav with sliding hover pill */}\n        <nav\n          className=\"relative hidden items-center gap-1 text-[0.9375rem] lg:flex lg:justify-self-center\"\n          onMouseLeave={handleNavLeave}\n        >\n          <span\n            ref={pillRef}\n            className=\"pointer-events-none absolute rounded-full bg-foreground/6 opacity-0 transition-all duration-200 dark:bg-white/10\"\n            aria-hidden=\"true\"\n          />\n          {links.map((link) => (\n            <a\n              key={link.href}\n              href={link.href}\n              aria-current={link.href === activeHref ? 'page' : undefined}\n              onMouseEnter={handleItemEnter}\n              className={`relative rounded-full px-3 py-1.5 ${\n                link.href === activeHref ? activeClass : inactiveClass\n              }`}\n            >\n              {link.label}\n            </a>\n          ))}\n          {cta && (\n            <a\n              href={cta.href}\n              aria-current={cta.href === activeHref ? 'page' : undefined}\n              onMouseEnter={handleItemEnter}\n              className={`relative rounded-full px-3 py-1.5 ${\n                cta.href === activeHref ? activeClass : inactiveClass\n              }`}\n            >\n              {cta.label}\n            </a>\n          )}\n        </nav>\n\n        {/* Desktop actions zone */}\n        <div className=\"hidden items-center gap-2 lg:flex lg:justify-self-end\">{children}</div>\n\n        {/* Mobile hamburger */}\n        <button\n          type=\"button\"\n          aria-label=\"Menu\"\n          aria-expanded={open}\n          aria-controls={panelId}\n          onClick={() => setOpen((v) => !v)}\n          className=\"grid size-9 place-items-center justify-self-end rounded-full border border-muted bg-muted lg:hidden\"\n        >\n          <span className=\"flex flex-col gap-1\">\n            <span className=\"h-0.5 w-4 rounded bg-current\" />\n            <span className=\"h-0.5 w-4 rounded bg-current\" />\n          </span>\n        </button>\n      </div>\n\n      {/* Mobile sheet */}\n      <div\n        id={panelId}\n        hidden={!open}\n        className=\"mt-2 rounded-3xl border border-glass-edge bg-glass-stronger p-4 shadow-[0_16px_48px_rgba(28,25,20,0.12)] backdrop-blur-2xl backdrop-saturate-150 lg:hidden\"\n      >\n        <nav className=\"flex flex-col gap-1 text-base\">\n          {links.map((link) => (\n            <a\n              key={link.href}\n              href={link.href}\n              aria-current={link.href === activeHref ? 'page' : undefined}\n              className={`rounded-xl px-4 py-2.5 ${\n                link.href === activeHref ? activeClass : inactiveClass\n              }`}\n            >\n              {link.label}\n            </a>\n          ))}\n        </nav>\n        {(cta || children) && (\n          <div className=\"mt-3 flex items-center justify-between gap-3 border-t border-foreground/10 px-2 pt-4 dark:border-white/6\">\n            {cta && (\n              <a\n                href={cta.href}\n                className=\"rounded-full bg-primary px-4 py-2 text-sm font-semibold text-primary-foreground\"\n              >\n                {cta.label}\n              </a>\n            )}\n            {children}\n          </div>\n        )}\n      </div>\n    </header>\n  );\n}\n",
      "type": "registry:ui"
    }
  ],
  "docs": "Drop <ThemeToggle /> or <LangSwitcher /> into the children slot — it renders in the desktop actions zone and the mobile sheet footer. Active state is controlled via activeHref.",
  "type": "registry:ui"
}