{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "nested-nav",
  "type": "registry:ui",
  "title": "Nested nav",
  "description": "A collapsible tree navigation built from nested node data, indented by depth with rotating chevrons on items that have children. Fits React docs sidebars.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/ui/nested-nav.tsx",
      "type": "registry:ui",
      "target": "components/ui/nested-nav.tsx",
      "content": "\"use client\"\nimport * as React from \"react\"\nimport { ChevronRightIcon } from \"lucide-react\"\nimport { cn } from \"@/lib/utils\"\n\n/** NestedNav — a collapsible tree of navigation groups that indents with depth. */\n\ntype NavNode = { id: string; label: string; children?: NavNode[] }\n\n// The Lumen settings tree.\nconst SAMPLE_NODES: NavNode[] = [\n  {\n    id: \"workspace\",\n    label: \"Workspace\",\n    children: [\n      { id: \"general\", label: \"General\" },\n      { id: \"members\", label: \"Members\" },\n      {\n        id: \"billing\",\n        label: \"Billing\",\n        children: [\n          { id: \"plans\", label: \"Plans\" },\n          { id: \"invoices\", label: \"Invoices\" },\n          { id: \"payment-methods\", label: \"Payment methods\" },\n        ],\n      },\n    ],\n  },\n  {\n    id: \"developers\",\n    label: \"Developers\",\n    children: [\n      { id: \"api-keys\", label: \"API keys\" },\n      { id: \"webhooks\", label: \"Webhooks\" },\n    ],\n  },\n  { id: \"audit-log\", label: \"Audit log\" },\n]\n\ntype NestedNavProps = {\n  /** Tree of nodes; any node with children becomes a collapsible group. */\n  nodes?: NavNode[]\n  className?: string\n}\n\nfunction NestedNav({ nodes = SAMPLE_NODES, className }: NestedNavProps) {\n  return (\n    <ul data-slot=\"nested-nav\" className={cn(\"space-y-0.5 text-sm\", className)}>\n      {nodes.map((n) => (\n        <NestedNavItem key={n.id} node={n} depth={0} />\n      ))}\n    </ul>\n  )\n}\nfunction NestedNavItem({ node, depth }: { node: NavNode; depth: number }) {\n  const [open, setOpen] = React.useState(true)\n  const has = !!node.children?.length\n  return (\n    <li>\n      <button\n        type=\"button\"\n        aria-expanded={has ? open : undefined}\n        className=\"flex w-full items-center gap-1 rounded-lg px-2 py-1.5 text-left text-fg-muted hover:bg-sunken hover:text-fg\"\n        style={{ paddingLeft: 8 + depth * 12 }}\n        onClick={() => has && setOpen((v) => !v)}\n      >\n        {has ? (\n          <ChevronRightIcon className={cn(\"size-3.5 transition-transform duration-[140ms]\", open && \"rotate-90\")} />\n        ) : (\n          <span className=\"size-3.5\" />\n        )}\n        {node.label}\n      </button>\n      {has && open ? (\n        <ul>\n          {node.children!.map((c) => (\n            <NestedNavItem key={c.id} node={c} depth={depth + 1} />\n          ))}\n        </ul>\n      ) : null}\n    </li>\n  )\n}\nexport { NestedNav }\nexport type { NavNode, NestedNavProps }\n"
    }
  ]
}
