{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "awwwards-nav",
  "type": "registry:ui",
  "dependencies": [
    "gsap",
    "@phosphor-icons/react"
  ],
  "files": [
    {
      "path": "components/ui/awwwards-nav.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport gsap from \"gsap\";\nimport { List, X } from \"@phosphor-icons/react\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * Awwwards Nav\n *\n * A glassmorphic bottom navigation pill with inline links and a \"More\" button.\n * Tapping \"More\" expands the bar upward with a smooth `power4.inOut` motion:\n * the inline links fade out, the button grows to full width, its icon flips to\n * an X, and a multi-column mega-menu reveals inside the expanded panel.\n *\n * Ported from the vanilla \"CodeGrid Awwwards Nav\" (GSAP) into a single,\n * self-contained, prop-driven React component. Positioning is left to the\n * consumer via `className`, so it works fixed to the viewport or absolutely\n * inside a positioned container.\n */\n\nexport interface AwwwardsNavLink {\n  label: string;\n  href: string;\n}\n\nexport interface AwwwardsNavColumn {\n  /** Column heading shown above its links. */\n  title: string;\n  /** Links listed under the heading. */\n  links: AwwwardsNavLink[];\n}\n\nexport interface AwwwardsNavProps {\n  /** Inline links shown in the collapsed bar. Defaults to a sample set. */\n  items?: AwwwardsNavLink[];\n  /** Columns revealed in the expanded mega-menu. Defaults to a sample set. */\n  columns?: AwwwardsNavColumn[];\n  /** Label on the expand/collapse button. Defaults to \"More\". */\n  moreLabel?: string;\n  /** Called whenever the panel opens (true) or closes (false). */\n  onOpenChange?: (open: boolean) => void;\n  /**\n   * Extra class names for the root nav. Use this to position it —\n   * e.g. `fixed bottom-6 left-1/2 -translate-x-1/2` (default) or\n   * `absolute` inside a positioned parent.\n   */\n  className?: string;\n}\n\nconst DEFAULT_ITEMS: AwwwardsNavLink[] = [\n  { label: \"Home\", href: \"#\" },\n  { label: \"Nominees\", href: \"#\" },\n  { label: \"Directory\", href: \"#\" },\n  { label: \"Collections\", href: \"#\" },\n];\n\nconst DEFAULT_COLUMNS: AwwwardsNavColumn[] = [\n  {\n    title: \"Awards\",\n    links: [\n      { label: \"Winners\", href: \"#\" },\n      { label: \"Site of the Day\", href: \"#\" },\n      { label: \"Nominees\", href: \"#\" },\n    ],\n  },\n  {\n    title: \"Inspiration\",\n    links: [\n      { label: \"Collections\", href: \"#\" },\n      { label: \"Elements\", href: \"#\" },\n      { label: \"Resources\", href: \"#\" },\n    ],\n  },\n  {\n    title: \"Directory\",\n    links: [\n      { label: \"Professionals\", href: \"#\" },\n      { label: \"Agencies\", href: \"#\" },\n      { label: \"Freelancers\", href: \"#\" },\n    ],\n  },\n  {\n    title: \"Market\",\n    links: [\n      { label: \"Jobs\", href: \"#\" },\n      { label: \"New Events\", href: \"#\" },\n      { label: \"Products\", href: \"#\" },\n    ],\n  },\n];\n\nconst COLLAPSED_HEIGHT = 60;\nconst EXPANDED_HEIGHT = 370;\n\nexport function AwwwardsNav({\n  items = DEFAULT_ITEMS,\n  columns = DEFAULT_COLUMNS,\n  moreLabel = \"More\",\n  onOpenChange,\n  className,\n}: AwwwardsNavProps) {\n  const navRef = useRef<HTMLElement>(null);\n  const navTopRef = useRef<HTMLDivElement>(null);\n  const navItemsRef = useRef<HTMLDivElement>(null);\n  const navHomeRef = useRef<HTMLDivElement>(null);\n\n  const openRef = useRef(false);\n  const animatingRef = useRef(false);\n  const [showClose, setShowClose] = useState(false);\n\n  const onOpenChangeRef = useRef(onOpenChange);\n  useEffect(() => {\n    onOpenChangeRef.current = onOpenChange;\n  }, [onOpenChange]);\n\n  // Establish the collapsed baseline imperatively (matches the source's gsap.set).\n  useEffect(() => {\n    const nav = navRef.current;\n    const navTop = navTopRef.current;\n    const navItems = navItemsRef.current;\n    const navHome = navHomeRef.current;\n    if (!nav || !navTop || !navItems || !navHome) return;\n\n    gsap.set(nav, { height: COLLAPSED_HEIGHT });\n    gsap.set(navTop, { opacity: 0, scale: 0.9, display: \"none\" });\n    gsap.set(navItems, { opacity: 1, display: \"flex\" });\n    gsap.set(navHome, { flexGrow: 0 });\n\n    return () => {\n      gsap.killTweensOf([nav, navTop, navItems, navHome]);\n    };\n  }, []);\n\n  const toggle = () => {\n    const nav = navRef.current;\n    const navTop = navTopRef.current;\n    const navItems = navItemsRef.current;\n    const navHome = navHomeRef.current;\n    if (!nav || !navTop || !navItems || !navHome || animatingRef.current) return;\n\n    animatingRef.current = true;\n    const opening = !openRef.current;\n    openRef.current = opening;\n    onOpenChangeRef.current?.(opening);\n\n    if (opening) {\n      gsap.to(nav, { height: EXPANDED_HEIGHT, duration: 0.75, ease: \"power4.inOut\" });\n      gsap.to(navItems, {\n        opacity: 0,\n        duration: 0.1,\n        onComplete: () => gsap.set(navItems, { display: \"none\" }),\n      });\n      gsap.to(navHome, {\n        flexGrow: 1,\n        duration: 0.2,\n        ease: \"power4.inOut\",\n        onComplete: () => setShowClose(true),\n      });\n      gsap.to(navTop, {\n        opacity: 1,\n        scale: 1,\n        duration: 0.3,\n        delay: 0.5,\n        onStart: () => gsap.set(navTop, { display: \"block\" }),\n        onComplete: () => {\n          animatingRef.current = false;\n        },\n      });\n    } else {\n      gsap.to(nav, { height: COLLAPSED_HEIGHT, duration: 0.75, ease: \"power4.inOut\", delay: 0.2 });\n      gsap.to(navTop, {\n        opacity: 0,\n        scale: 0.9,\n        duration: 0.2,\n        onComplete: () => gsap.set(navTop, { display: \"none\" }),\n      });\n      gsap.to(navHome, {\n        flexGrow: 0,\n        duration: 0.2,\n        ease: \"power4.inOut\",\n        onComplete: () => setShowClose(false),\n      });\n      gsap.to(navItems, {\n        opacity: 1,\n        duration: 0.2,\n        delay: 0.5,\n        onStart: () => gsap.set(navItems, { display: \"flex\" }),\n        onComplete: () => {\n          animatingRef.current = false;\n        },\n      });\n    }\n  };\n\n  return (\n    <nav\n      ref={navRef}\n      className={cn(\n        \"fixed bottom-6 left-1/2 z-50 -translate-x-1/2\",\n        \"h-[60px] w-[min(680px,92vw)] overflow-hidden rounded-xl border backdrop-blur-xl\",\n        \"border-black/10 bg-white/70 dark:border-white/25 dark:bg-black/75\",\n        className,\n      )}\n    >\n      {/* Expanded mega-menu, fills the space above the bottom row */}\n      <div ref={navTopRef} className=\"absolute inset-x-0 top-0 bottom-[60px] hidden p-2.5\">\n        <div className=\"flex h-full w-full gap-0 rounded-[10px] border border-black/[0.06] bg-black/[0.03] p-5 dark:border-white/[0.06] dark:bg-white/[0.04]\">\n          {columns.map((col, ci) => (\n            <div\n              key={col.title}\n              className={cn(\n                \"flex flex-1 flex-col gap-1\",\n                ci > 0 && \"border-l border-dashed border-black/15 pl-4 dark:border-white/20\",\n              )}\n            >\n              <div className=\"mb-3 flex items-center gap-2\">\n                <span className=\"h-1 w-1 shrink-0 rounded-full bg-black dark:bg-white\" />\n                <p className=\"text-sm text-black/70 dark:text-white/75\">{col.title}</p>\n              </div>\n              {col.links.map((link) => (\n                <a\n                  key={link.label}\n                  href={link.href}\n                  className=\"block py-2 text-sm text-black transition-colors hover:text-black/50 dark:text-white dark:hover:text-white/60\"\n                >\n                  {link.label}\n                </a>\n              ))}\n            </div>\n          ))}\n        </div>\n      </div>\n\n      {/* Collapsed bottom row: More button + inline items */}\n      <div className=\"absolute inset-x-0 bottom-0 flex h-[60px] gap-1.5 p-2.5\">\n        <div\n          ref={navHomeRef}\n          role=\"button\"\n          tabIndex={0}\n          aria-expanded={showClose}\n          aria-label={showClose ? \"Close menu\" : \"Open menu\"}\n          onClick={toggle}\n          onKeyDown={(e) => {\n            if (e.key === \"Enter\" || e.key === \" \") {\n              e.preventDefault();\n              toggle();\n            }\n          }}\n          className={cn(\n            \"flex shrink-0 cursor-pointer select-none items-center justify-center gap-2.5 rounded-[10px] border px-5 text-sm transition-colors\",\n            \"border-black/10 bg-black/[0.04] text-neutral-600 hover:bg-black/[0.08] hover:text-black\",\n            \"dark:border-white/10 dark:bg-white/[0.06] dark:text-neutral-300 dark:hover:bg-white/[0.12] dark:hover:text-white\",\n            showClose && \"bg-black/[0.08] text-black dark:bg-white/[0.12] dark:text-white\",\n          )}\n        >\n          {showClose ? (\n            <X weight=\"light\" className=\"h-4 w-4 text-black dark:text-white\" />\n          ) : (\n            <List weight=\"light\" className=\"h-4 w-4 text-black dark:text-white\" />\n          )}\n          <span>{moreLabel}</span>\n        </div>\n\n        <div ref={navItemsRef} className=\"flex min-w-0 flex-[4] items-center gap-1.5\">\n          {items.map((item) => (\n            <div\n              key={item.label}\n              className=\"flex h-full flex-1 items-center justify-center rounded-[10px] border border-black/15 transition-colors hover:border-black/40 dark:border-white/20 dark:hover:border-white/50\"\n            >\n              <a\n                href={item.href}\n                className=\"px-2 text-center text-sm text-neutral-600 transition-colors hover:text-black dark:text-neutral-400 dark:hover:text-white\"\n              >\n                {item.label}\n              </a>\n            </div>\n          ))}\n        </div>\n      </div>\n    </nav>\n  );\n}\n\nexport default AwwwardsNav;\n",
      "type": "registry:ui",
      "target": "components/ui/awwwards-nav.tsx"
    }
  ]
}
