{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "toolbar",
  "title": "Toolbar",
  "description": "The floating and docked toolbars, in standard and vibrant color.",
  "registryDependencies": [
    "https://guillermo-rebolledo.github.io/materialcn/r/materialcn-theme.json",
    "https://guillermo-rebolledo.github.io/materialcn/r/separator.json",
    "https://guillermo-rebolledo.github.io/materialcn/r/utils.json"
  ],
  "files": [
    {
      "path": "src/components/ui/toolbar.tsx",
      "content": "import { useEffect, useRef, type ComponentProps, type KeyboardEvent } from \"react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Separator } from \"./separator\"\n\n/** @deprecated Use `variant` (`floating` | `docked`) — the kit has no 96dp toolbar. */\ntype ToolbarPresentation = \"standard\" | \"expressive\"\ntype ToolbarVariant = \"floating\" | \"docked\"\ntype ToolbarColor = \"standard\" | \"vibrant\"\n\n/**\n * Kit geometry (Toolbars page): every toolbar is 64dp. `floating` has 32dp\n * corners, 12×8dp padding, a 4dp gap and elevation level 3; `docked` is flat,\n * square and full-width with 12×16dp padding and an 8dp gap. `standard`\n * colour is Surface Container, `vibrant` is Primary Container.\n */\ntype ToolbarProps = ComponentProps<\"div\"> & {\n  color?: ToolbarColor\n  /** @deprecated Use `variant`. `standard` maps to `floating`. */\n  presentation?: ToolbarPresentation\n  variant?: ToolbarVariant\n}\n\nfunction Toolbar({\n  \"aria-label\": ariaLabel = \"Tools\",\n  className,\n  color = \"standard\",\n  onKeyDown,\n  presentation,\n  ref,\n  variant = \"floating\",\n  ...props\n}: ToolbarProps) {\n  void presentation\n  const rootRef = useRef<HTMLDivElement>(null)\n  const getControls = (root: HTMLElement) => Array.from(\n    root.querySelectorAll<HTMLElement>('button:not(:disabled), a[href], [role=\"button\"]:not([aria-disabled=\"true\"])'),\n  )\n  const setTabStop = (controls: HTMLElement[], active: HTMLElement) => {\n    controls.forEach((control) => {\n      control.tabIndex = control === active ? 0 : -1\n    })\n  }\n  const ensureTabStop = () => {\n    const controls = rootRef.current ? getControls(rootRef.current) : []\n    if (!controls.length) return\n    const focused = controls.find((control) => control === document.activeElement)\n    const active = focused ?? controls.find((control) => control.tabIndex === 0) ?? controls[0]\n    setTabStop(controls, active)\n  }\n\n  useEffect(() => {\n    if (!rootRef.current) return\n    ensureTabStop()\n    const observer = new MutationObserver(ensureTabStop)\n    observer.observe(rootRef.current, {\n      attributeFilter: [\"aria-disabled\", \"disabled\"],\n      attributes: true,\n      childList: true,\n      subtree: true,\n    })\n    return () => observer.disconnect()\n  }, [])\n\n  const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n    onKeyDown?.(event)\n    if (event.defaultPrevented || ![\"ArrowLeft\", \"ArrowRight\", \"Home\", \"End\"].includes(event.key)) return\n    const controls = getControls(event.currentTarget)\n    if (!controls.length) return\n    const index = controls.indexOf(document.activeElement as HTMLElement)\n    const next = event.key === \"Home\"\n      ? 0\n      : event.key === \"End\"\n        ? controls.length - 1\n        : event.key === \"ArrowRight\"\n          ? (index + 1) % controls.length\n          : (index - 1 + controls.length) % controls.length\n    event.preventDefault()\n    if (controls[next]) setTabStop(controls, controls[next])\n    controls[next]?.focus()\n  }\n  return (\n    <div\n      {...props}\n      ref={(node) => {\n        rootRef.current = node\n        if (typeof ref === \"function\") ref(node)\n        else if (ref) ref.current = node\n      }}\n      role=\"toolbar\"\n      aria-label={ariaLabel}\n      data-slot=\"toolbar\"\n      data-variant={variant}\n      data-color={color}\n      className={cn(\n        \"flex min-h-16 max-w-full items-center overflow-x-auto text-foreground\",\n        variant === \"floating\"\n          ? \"w-fit gap-1 rounded-m3-xl-increased px-2 py-3 shadow-m3-3\"\n          : \"w-full gap-2 px-4 py-3\",\n        color === \"vibrant\"\n          ? \"bg-m3-primary-container text-m3-on-primary-container\"\n          : \"bg-m3-surface-container\",\n        className,\n      )}\n      onKeyDown={handleKeyDown}\n      onFocusCapture={(event) => {\n        const controls = getControls(event.currentTarget)\n        const focused = controls.find((control) => control === event.target)\n        if (focused) setTabStop(controls, focused)\n      }}\n    />\n  )\n}\n\nfunction ToolbarGroup({ className, ...props }: ComponentProps<\"div\">) {\n  return <div {...props} role=\"group\" data-slot=\"toolbar-group\" className={cn(\"flex shrink-0 items-center gap-1\", className)} />\n}\n\nfunction ToolbarLabel({ className, ...props }: ComponentProps<\"span\">) {\n  return <span {...props} data-slot=\"toolbar-label\" className={cn(\"shrink-0 px-2 text-m3-label-lg text-muted-foreground\", className)} />\n}\n\nfunction ToolbarDivider({ className, ...props }: ComponentProps<typeof Separator>) {\n  return <Separator {...props} orientation=\"vertical\" data-slot=\"toolbar-divider\" className={cn(\"mx-1 h-8\", className)} />\n}\n\nfunction ToolbarOverflow({ className, ...props }: ComponentProps<\"div\">) {\n  return <div {...props} data-slot=\"toolbar-overflow\" className={cn(\"ml-auto flex shrink-0 items-center\", className)} />\n}\n\nfunction ToolbarFAB({ className, ...props }: ComponentProps<\"div\">) {\n  return <div {...props} data-slot=\"toolbar-fab\" className={cn(\"ml-2 flex shrink-0 items-center\", className)} />\n}\n\nexport {\n  Toolbar,\n  ToolbarDivider,\n  ToolbarFAB,\n  ToolbarGroup,\n  ToolbarLabel,\n  ToolbarOverflow,\n  type ToolbarColor,\n  type ToolbarPresentation,\n  type ToolbarProps,\n  type ToolbarVariant,\n}\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "navigation"
  ],
  "type": "registry:ui"
}