{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"flex-navbar","type":"registry:ui","title":"Flex Navbar","description":"Icon navbar whose items spring open to reveal a tinted label on hover or focus while their neighbours flex aside.","dependencies":["motion"],"registryDependencies":[],"files":[{"path":"registry/ui/flex-navbar.tsx","type":"registry:ui","content":"\"use client\";\n\nimport { useState, type ReactNode } from \"react\";\nimport { motion, useReducedMotion } from \"motion/react\";\n\nexport interface FlexNavbarItem {\n  label: string;\n  icon: ReactNode;\n  /** Accent for the expanded pill (any CSS color). Falls back to `accent`. */\n  color?: string;\n  onClick?: () => void;\n}\n\nexport interface FlexNavbarProps {\n  items: FlexNavbarItem[];\n  /** Index of the active item at first render. */\n  defaultActive?: number;\n  /** Default accent color for items without their own. */\n  accent?: string;\n  /** Keep the active item's label open when nothing is hovered. */\n  showActiveLabel?: boolean;\n  /** Spring bounce, 0 (none) to 0.6. */\n  bounce?: number;\n  /** Icon size in px. */\n  iconSize?: number;\n  onChange?: (index: number) => void;\n  className?: string;\n}\n\n/**\n * Icon-only navbar whose items flex open to reveal their label. The hovered (or focused)\n * item expands and its neighbours make room with a spring; the active item stays open at rest.\n */\nexport function FlexNavbar({\n  items,\n  defaultActive = 0,\n  accent = \"#a78bfa\",\n  showActiveLabel = true,\n  bounce = 0.35,\n  iconSize = 20,\n  onChange,\n  className,\n}: FlexNavbarProps) {\n  const [active, setActive] = useState(defaultActive);\n  const [hover, setHover] = useState<number | null>(null);\n  const reduce = useReducedMotion();\n  const open = hover ?? (showActiveLabel ? active : -1);\n  const spring = reduce ? { duration: 0 } : { type: \"spring\" as const, bounce, duration: 0.55 };\n\n  return (\n    <nav\n      aria-label=\"Main\"\n      onPointerLeave={() => setHover(null)}\n      className={`flex items-center gap-1 rounded-full border border-border bg-card/80 p-1.5 shadow-[0_20px_50px_-24px_rgba(0,0,0,.7)] backdrop-blur-xl ${className ?? \"\"}`}\n    >\n      {items.map((item, i) => {\n        const on = i === open;\n        const tint = item.color ?? accent;\n        return (\n          <motion.button\n            key={item.label}\n            type=\"button\"\n            aria-label={item.label}\n            aria-current={i === active ? \"page\" : undefined}\n            onPointerEnter={() => setHover(i)}\n            onFocus={() => setHover(i)}\n            onBlur={() => setHover(null)}\n            onClick={() => {\n              setActive(i);\n              onChange?.(i);\n              item.onClick?.();\n            }}\n            whileTap={reduce ? undefined : { scale: 0.94 }}\n            transition={spring}\n            className={`relative flex h-11 items-center rounded-full px-3 outline-none transition-colors duration-300 focus-visible:ring-2 focus-visible:ring-ring ${\n              on ? \"\" : \"text-muted-foreground hover:text-foreground\"\n            }`}\n            style={on ? { color: tint } : undefined}\n          >\n            <motion.span\n              aria-hidden\n              initial={false}\n              animate={{ opacity: on ? 0.16 : 0, scale: on ? 1 : 0.8 }}\n              transition={spring}\n              className=\"absolute inset-0 rounded-full\"\n              style={{ backgroundColor: tint }}\n            />\n            <span className=\"relative grid shrink-0 place-items-center [&>svg]:size-full\" style={{ width: iconSize, height: iconSize }}>\n              {item.icon}\n            </span>\n            <motion.span\n              aria-hidden\n              initial={false}\n              animate={{ width: on ? \"auto\" : 0, opacity: on ? 1 : 0, marginLeft: on ? 8 : 0, filter: on || reduce ? \"blur(0px)\" : \"blur(4px)\" }}\n              transition={spring}\n              className=\"relative overflow-hidden whitespace-nowrap text-sm font-medium\"\n            >\n              {item.label}\n            </motion.span>\n          </motion.button>\n        );\n      })}\n    </nav>\n  );\n}\n"}]}