{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "expanding-icon-tabs",
  "title": "Expanding Icon Tabs",
  "author": "henriquegpb <https://github.com/henriquegpb>",
  "description": "An icon bar where the chosen tab widens to reveal its label and the rest of the row slides over to make room.",
  "dependencies": [
    "lucide-react"
  ],
  "files": [
    {
      "path": "registry/microkit/expanding-icon-tabs.tsx",
      "content": "\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport type { KeyboardEvent as ReactKeyboardEvent } from \"react\";\nimport { Activity, Compass, CreditCard, SlidersHorizontal, Users } from \"lucide-react\";\nimport type { LucideIcon } from \"lucide-react\";\n\ntype TabItem = { id: string; label: string; icon: LucideIcon } | { separator: true };\n\nconst items: TabItem[] = [\n  { id: \"overview\", label: \"Overview\", icon: Compass },\n  { id: \"activity\", label: \"Activity\", icon: Activity },\n  { separator: true },\n  { id: \"filters\", label: \"Filters\", icon: SlidersHorizontal },\n  { id: \"members\", label: \"Members\", icon: Users },\n  { id: \"billing\", label: \"Billing\", icon: CreditCard },\n];\n\nexport function ExpandingIconTabs() {\n  const [active, setActive] = useState<string | null>(null);\n  const rootRef = useRef<HTMLDivElement>(null);\n\n  useEffect(() => {\n    if (!active) return;\n    const region = rootRef.current?.parentElement;\n    if (!region) return;\n    const handlePointerDown = (event: Event) => {\n      if (!rootRef.current?.contains(event.target as Node)) setActive(null);\n    };\n    region.addEventListener(\"pointerdown\", handlePointerDown);\n    return () => region.removeEventListener(\"pointerdown\", handlePointerDown);\n  }, [active]);\n\n  const moveFocus = (delta: number) => {\n    const tabs = Array.from(rootRef.current?.querySelectorAll<HTMLButtonElement>(\"[data-tab]\") ?? []);\n    if (!tabs.length) return;\n    const index = tabs.indexOf(document.activeElement as HTMLButtonElement);\n    const next = index < 0 ? 0 : (index + delta + tabs.length) % tabs.length;\n    tabs[next].focus({ preventScroll: true });\n  };\n\n  const handleKeyDown = (event: ReactKeyboardEvent<HTMLDivElement>) => {\n    if (event.key === \"ArrowRight\" || event.key === \"ArrowLeft\") {\n      event.preventDefault();\n      moveFocus(event.key === \"ArrowRight\" ? 1 : -1);\n      return;\n    }\n    if (event.key === \"Escape\" && active) {\n      event.preventDefault();\n      setActive(null);\n    }\n  };\n\n  return (\n    <div\n      className=\"flex max-w-full flex-wrap items-center gap-1 rounded-xl border border-[light-dark(#dfe3ea,#2b2f36)] bg-[light-dark(#ffffff,#121418)] p-1 text-[11px] text-[light-dark(#262d38,#dfe2e5)] shadow-[inset_0_1px_0_rgba(255,255,255,.04),0_10px_24px_rgba(0,0,0,.35)]\"\n      role=\"toolbar\"\n      aria-label=\"Workspace views\"\n      ref={rootRef}\n      onKeyDown={handleKeyDown}\n    >\n      {items.map((item, index) =>\n        \"separator\" in item ? (\n          <span\n            key={`separator-${index}`}\n            className=\"mx-[2px] h-[18px] w-px flex-none bg-[light-dark(#e7eaef,#23262c)]\"\n            role=\"separator\"\n            aria-orientation=\"vertical\"\n          />\n        ) : (\n          <button\n            key={item.id}\n            type=\"button\"\n            className={`inline-flex h-[30px] items-center rounded-[9px] border-0 text-[11px] [transition:gap_.5s_cubic-bezier(.32,.72,0,1),padding_.5s_cubic-bezier(.32,.72,0,1),background-color_.3s_ease,color_.3s_ease] motion-reduce:[transition-duration:.01ms] focus-visible:outline focus-visible:outline-[1.5px] focus-visible:outline-offset-[-1.5px] focus-visible:outline-[#f97316] ${\n              active === item.id\n                ? \"gap-1.5 bg-[light-dark(#e7eaef,#22262c)] px-[11px] text-[light-dark(#14181e,#f4f5f7)]\"\n                : \"gap-0 bg-transparent px-2 text-[light-dark(#69727f,#868d97)] hover:bg-[light-dark(#f0f2f5,#1b1e23)] hover:text-[light-dark(#262d38,#dfe2e5)]\"\n            }`}\n            data-tab=\"\"\n            aria-label={item.label}\n            aria-pressed={active === item.id}\n            onClick={() => setActive(active === item.id ? null : item.id)}\n          >\n            <span\n              className={`grid flex-none place-items-center [transition:color_.3s_ease] motion-reduce:[transition-duration:.01ms] ${\n                active === item.id ? \"text-[#f97316]\" : \"\"\n              }`}\n            >\n              <item.icon size={15} strokeWidth={1.8} aria-hidden=\"true\" />\n            </span>\n            <span\n              className={`grid overflow-hidden [transition:grid-template-columns_.5s_cubic-bezier(.32,.72,0,1),opacity_.3s_ease] motion-reduce:[transition-duration:.01ms] ${\n                active === item.id ? \"grid-cols-[1fr] opacity-100\" : \"grid-cols-[0fr] opacity-0\"\n              }`}\n              aria-hidden=\"true\"\n            >\n              <span className=\"min-w-0 overflow-hidden whitespace-nowrap\">{item.label}</span>\n            </span>\n          </button>\n        ),\n      )}\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "@components/microkit/expanding-icon-tabs.tsx"
    }
  ],
  "docs": "Live preview and the CSS, JavaScript and Tailwind variants: https://microkit.co/components/expanding-icon-tabs",
  "categories": [
    "navigation",
    "click"
  ],
  "type": "registry:component"
}