{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "toolbar",
  "title": "Toolbar",
  "description": "One highlight springs between the toolbar's buttons, and presses pop back.",
  "dependencies": [
    "@ui-sdk/core@0.1.0-beta.2",
    "@ui-sdk/react@0.1.0-beta.2"
  ],
  "registryDependencies": [
    "@keyframery/motion"
  ],
  "files": [
    {
      "path": "registry/components/keyframery/primitives/toolbar.tsx",
      "content": "\"use client\"\n\n/* Animated drop-in for `@ui-sdk/react/toolbar`: same parts, same props. Swap the import and keep your code.\n   This file adds motion only. Colours, radii, shadows and spacing stay yours.\n   - Glide: one highlight springs from item to item under the pointer or keyboard focus, instead of\n     each item lighting up on its own. It is the toolbar's `::before`; give it a colour and radius with\n     `before:` classes. The default follows the text colour.\n   - Press: items give under the pointer and spring back with a small pop.\n   `ToolbarToggle` and `ToolbarToggleGroup` are extra: `@ui-sdk/react/toggle` parts with the same press. */\n\nimport { Toggle as TogglePart, ToggleGroup as ToggleGroupPart } from \"@ui-sdk/react/toggle\"\nimport {\n  Toolbar as ToolbarRoot,\n  ToolbarButton as ToolbarButtonPart,\n  ToolbarLink as ToolbarLinkPart,\n} from \"@ui-sdk/react/toolbar\"\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport * from \"@ui-sdk/react/toolbar\"\n\n/* Everything the highlight can rest on. Inputs keep their own field look. */\nconst ITEM =\n  '[data-slot=\"toolbar-button\"],[data-slot=\"toolbar-link\"],[data-slot=\"toggle\"]'\nconst MARK = \"data-kf-toolbar-hl\"\n\n/* Colours and shadows ease as the pointer arrives; the press springs back with a pop. */\nconst press = cn(\n  \"[transition:color_calc(150ms*var(--kf-speed,1))_var(--ease-house),background-color_calc(150ms*var(--kf-speed,1))_var(--ease-house),box-shadow_calc(150ms*var(--kf-speed,1))_var(--ease-house),scale_calc(260ms*var(--kf-speed,1))_var(--ease-pop)]\",\n  \"not-data-disabled:active:scale-[0.92] not-data-disabled:active:[transition-duration:calc(100ms*var(--kf-speed,1))]\",\n  \"motion-reduce:[transition:none]!\",\n)\n\n/* Moves the mark to `item`, or hides the highlight where it is (so it can glide on from there). */\nfunction mark(root: HTMLElement, item: Element | null) {\n  if (!item || item.hasAttribute(\"data-disabled\")) {\n    root.setAttribute(\"data-kf-idle\", \"\")\n    return\n  }\n  for (const old of root.querySelectorAll(`[${MARK}]`)) if (old !== item) old.removeAttribute(MARK)\n  item.setAttribute(MARK, \"\")\n  root.removeAttribute(\"data-kf-idle\")\n  /* The first time, the highlight appears in place; from then on it glides. */\n  if (!root.hasAttribute(\"data-kf-glide\")) setTimeout(() => root.setAttribute(\"data-kf-glide\", \"\"), 40)\n}\n\nfunction itemFrom(root: HTMLElement, target: EventTarget | null) {\n  const item = target instanceof Element ? target.closest(ITEM) : null\n  return item && root.contains(item) ? item : null\n}\n\nfunction Toolbar({\n  className,\n  onPointerOver,\n  onPointerLeave,\n  onFocus,\n  onBlur,\n  onClick,\n  ...props\n}: React.ComponentProps<typeof ToolbarRoot>) {\n  const hovering = React.useRef(false)\n  return (\n    <ToolbarRoot\n      className={cn(\n        \"relative isolate [anchor-scope:--kf-toolbar-hl]\",\n        \"[&_[data-kf-toolbar-hl]]:[anchor-name:--kf-toolbar-hl]\",\n        \"before:pointer-events-none before:absolute before:-z-10 before:bg-[color-mix(in_oklch,currentColor_9%,transparent)]\",\n        \"before:[position-anchor:--kf-toolbar-hl] before:top-[anchor(top)] before:right-[anchor(right)] before:bottom-[anchor(bottom)] before:left-[anchor(left)]\",\n        \"before:scale-100 before:opacity-100 before:transition-[opacity,scale] before:duration-[calc(200ms*var(--kf-speed,1))] before:ease-house\",\n        \"data-kf-glide:before:[transition:top_calc(360ms*var(--kf-speed,1))_var(--ease-spring),right_calc(360ms*var(--kf-speed,1))_var(--ease-spring),bottom_calc(360ms*var(--kf-speed,1))_var(--ease-spring),left_calc(360ms*var(--kf-speed,1))_var(--ease-spring),opacity_calc(200ms*var(--kf-speed,1))_var(--ease-house),scale_calc(200ms*var(--kf-speed,1))_var(--ease-house)]\",\n        \"data-kf-idle:before:scale-[0.92] data-kf-idle:before:opacity-0 not-has-[[data-kf-toolbar-hl]]:before:opacity-0\",\n        \"motion-reduce:before:[transition:none]!\",\n        className,\n      )}\n      onPointerOver={(event) => {\n        onPointerOver?.(event)\n        hovering.current = true\n        const item = itemFrom(event.currentTarget, event.target)\n        if (item) mark(event.currentTarget, item)\n      }}\n      onPointerLeave={(event) => {\n        onPointerLeave?.(event)\n        hovering.current = false\n        const root = event.currentTarget\n        mark(root, itemFrom(root, root.querySelector(\":focus-visible\")))\n      }}\n      onFocus={(event) => {\n        onFocus?.(event)\n        const target = event.target as Element\n        if (target.matches(\":focus-visible\")) mark(event.currentTarget, itemFrom(event.currentTarget, target))\n      }}\n      onBlur={(event) => {\n        onBlur?.(event)\n        const root = event.currentTarget\n        if (!hovering.current && !root.contains(event.relatedTarget as Node | null)) mark(root, null)\n      }}\n      onClick={(event) => {\n        onClick?.(event)\n        const item = itemFrom(event.currentTarget, event.target)\n        if (item) mark(event.currentTarget, item)\n      }}\n      {...props}\n    />\n  )\n}\n\nfunction ToolbarButton({ className, ...props }: React.ComponentProps<typeof ToolbarButtonPart>) {\n  return <ToolbarButtonPart className={cn(press, className)} {...props} />\n}\n\nfunction ToolbarLink({ className, ...props }: React.ComponentProps<typeof ToolbarLinkPart>) {\n  return <ToolbarLinkPart className={cn(press, className)} {...props} />\n}\n\n/* A toggle joins the toolbar's arrow keys on its own. Pressed, its surface pops in. */\nfunction ToolbarToggle({ className, ...props }: React.ComponentProps<typeof TogglePart>) {\n  return <TogglePart className={cn(press, className)} {...props} />\n}\n\nfunction ToolbarToggleGroup<T extends string = string>({\n  className,\n  ...props\n}: React.ComponentProps<typeof ToggleGroupPart<T>>) {\n  return <ToggleGroupPart className={cn(className)} {...props} />\n}\n\nexport { Toolbar, ToolbarButton, ToolbarLink, ToolbarToggle, ToolbarToggleGroup }\n",
      "type": "registry:component",
      "target": "components/keyframery/primitives/toolbar.tsx"
    },
    {
      "path": "registry/components/keyframery/toolbar.tsx",
      "content": "\"use client\"\n\n/* Styled toolbar: the animated primitive plus the Keyframery look. */\n\nimport * as React from \"react\"\n\nimport {\n  Toolbar as ToolbarRoot,\n  ToolbarButton as ToolbarButtonPart,\n  ToolbarGroup as ToolbarGroupPart,\n  ToolbarInput as ToolbarInputPart,\n  ToolbarLink as ToolbarLinkPart,\n  ToolbarSeparator as ToolbarSeparatorPart,\n  ToolbarToggle as TogglePart,\n  ToolbarToggleGroup as ToggleGroupPart,\n} from \"@/components/keyframery/primitives/toolbar\"\nimport { cn } from \"@/lib/utils\"\n\n/* One box for everything you can press in the bar: buttons, links and toggles. */\nconst item = cn(\n  \"relative inline-flex h-7 min-w-7 shrink-0 cursor-pointer items-center justify-center gap-1.5 rounded-[8px] px-1.5\",\n  \"text-[13px] leading-none font-medium whitespace-nowrap text-muted-foreground outline-none select-none\",\n  \"[&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\",\n  \"not-data-disabled:hover:text-foreground data-kf-toolbar-hl:not-data-disabled:text-foreground\",\n  \"focus-visible:z-10 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-popover\",\n  \"data-disabled:cursor-not-allowed data-disabled:opacity-40\",\n)\n\nconst row =\n  \"flex items-center gap-0.5 data-[orientation=vertical]:flex-col data-[orientation=vertical]:items-stretch\"\n\nfunction Toolbar({\n  className,\n  ...props\n}: React.ComponentProps<typeof ToolbarRoot>) {\n  return (\n    <ToolbarRoot\n      className={cn(\n        row,\n        \"w-fit rounded-[12px] bg-popover p-1 text-popover-foreground\",\n        /* The gliding highlight. */\n        \"before:rounded-[8px] before:bg-accent dark:before:bg-accent/70\",\n        \"shadow-[0_0_0_1px_rgb(0_0_0/0.06),0_2px_6px_-2px_rgb(0_0_0/0.08),0_12px_32px_-8px_rgb(0_0_0/0.18)]\",\n        \"dark:shadow-[0_0_0_1px_rgb(255_255_255/0.08),0_12px_32px_-8px_rgb(0_0_0/0.7)]\",\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction ToolbarButton({\n  className,\n  ...props\n}: React.ComponentProps<typeof ToolbarButtonPart>) {\n  return (\n    <ToolbarButtonPart\n      className={cn(item, className)}\n      {...props}\n    />\n  )\n}\n\nfunction ToolbarLink({\n  className,\n  ...props\n}: React.ComponentProps<typeof ToolbarLinkPart>) {\n  return (\n    <ToolbarLinkPart\n      className={cn(item, \"px-2\", className)}\n      {...props}\n    />\n  )\n}\n\n/* A toggle joins the bar's arrow keys on its own. Pressed, it becomes a key. */\nfunction ToolbarToggle({\n  className,\n  ...props\n}: React.ComponentProps<typeof TogglePart>) {\n  return (\n    <TogglePart\n      className={cn(\n        item,\n        \"data-pressed:bg-background data-pressed:text-foreground\",\n        \"data-pressed:shadow-[0_0_0_1px_rgb(0_0_0/0.06),0_1px_1px_rgb(0_0_0/0.05),0_3px_6px_-2px_rgb(0_0_0/0.1)]\",\n        \"dark:data-pressed:bg-accent dark:data-pressed:shadow-[0_0_0_1px_rgb(255_255_255/0.07),inset_0_1px_0_rgb(255_255_255/0.08),0_2px_6px_-1px_rgb(0_0_0/0.6)]\",\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction ToolbarToggleGroup<T extends string = string>({\n  className,\n  ...props\n}: React.ComponentProps<typeof ToggleGroupPart<T>>) {\n  return <ToggleGroupPart className={cn(row, className)} {...props} />\n}\n\nfunction ToolbarGroup({\n  className,\n  ...props\n}: React.ComponentProps<typeof ToolbarGroupPart>) {\n  return <ToolbarGroupPart className={cn(row, className)} {...props} />\n}\n\nfunction ToolbarInput({\n  className,\n  ...props\n}: React.ComponentProps<typeof ToolbarInputPart>) {\n  return (\n    <ToolbarInputPart\n      className={cn(\n        \"h-7 min-w-0 rounded-[8px] bg-background px-2 text-[13px] text-foreground outline-none placeholder:text-muted-foreground\",\n        \"shadow-[0_0_0_1px_rgb(0_0_0/0.09),0_1px_2px_rgb(0_0_0/0.05)] dark:shadow-[0_0_0_1px_rgb(255_255_255/0.1)]\",\n        \"transition-shadow duration-[calc(150ms*var(--kf-speed,1))] motion-reduce:transition-none!\",\n        \"not-data-disabled:hover:shadow-[0_0_0_1px_rgb(0_0_0/0.16),0_1px_2px_rgb(0_0_0/0.05)] dark:not-data-disabled:hover:shadow-[0_0_0_1px_rgb(255_255_255/0.18)]\",\n        \"focus-visible:shadow-[0_0_0_1px_var(--ring)] focus-visible:ring-[3px] focus-visible:ring-ring/25\",\n        \"dark:focus-visible:shadow-[0_0_0_1px_var(--ring)]\",\n        \"data-disabled:cursor-not-allowed data-disabled:opacity-50\",\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\n/* The line runs across the bar, so it stands upright in a horizontal one. */\nfunction ToolbarSeparator({\n  className,\n  ...props\n}: React.ComponentProps<typeof ToolbarSeparatorPart>) {\n  return (\n    <ToolbarSeparatorPart\n      className={cn(\n        \"shrink-0 bg-border\",\n        \"data-[orientation=vertical]:mx-1 data-[orientation=vertical]:h-4 data-[orientation=vertical]:w-px\",\n        \"data-[orientation=horizontal]:my-1 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-4 data-[orientation=horizontal]:self-center\",\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\nexport {\n  Toolbar,\n  ToolbarButton,\n  ToolbarGroup,\n  ToolbarInput,\n  ToolbarLink,\n  ToolbarSeparator,\n  ToolbarToggle,\n  ToolbarToggleGroup,\n}\n",
      "type": "registry:component",
      "target": "components/keyframery/toolbar.tsx"
    }
  ],
  "type": "registry:component"
}