{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "button",
  "title": "Button",
  "description": "Brand-restyled shadcn Button. Pill shape, ink label on the accent, the `link` variant dropped (orange is never text on a light ground). It presses in a pixel while held, unless it opens a popup; while its popup is open (aria-expanded) it holds its hover fill. `loading` keeps the label in place for width, lays a Spinner over it, sets aria-busy and disables the button; rendered as a link or another element, a loading or disabled Button is aria-disabled and refuses clicks and Enter, whichever element carries the label. The focus ring is the kit's shared --text outline, the transition takes the brand ease and stops under reduced motion.",
  "dependencies": [
    "@base-ui/react@1.9.0",
    "class-variance-authority@0.7.1"
  ],
  "registryDependencies": [
    "@waimakers/utils",
    "@waimakers/theme",
    "@waimakers/spinner"
  ],
  "files": [
    {
      "path": "src/components/ui/button.tsx",
      "content": "import { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport { type VariantProps, cva } from \"class-variance-authority\";\nimport {\n  type KeyboardEvent,\n  type MouseEvent,\n  type ReactElement,\n  type ReactNode,\n  type Ref,\n  createElement,\n  isValidElement,\n} from \"react\";\n\nimport { cn, focusRing, invalidRing } from \"../../lib/utils\";\nimport { Spinner } from \"./spinner\";\n\nconst buttonVariants = cva(\n  cn(\n    \"relative inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-full text-sm font-semibold transition-[color,background-color,border-color,translate] ease-brand motion-reduce:transition-none active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:not-aria-busy:opacity-50 aria-busy:opacity-100 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\",\n    focusRing,\n    invalidRing,\n  ),\n  {\n    variants: {\n      variant: {\n        default:\n          \"bg-primary text-primary-foreground hover:bg-[var(--btn-primary-bg-hover)] aria-expanded:bg-[var(--btn-primary-bg-hover)]\",\n        destructive:\n          \"bg-destructive text-destructive-foreground hover:bg-brand-danger-strong aria-expanded:bg-brand-danger-strong\",\n        outline:\n          \"border border-input bg-background text-foreground hover:bg-muted aria-expanded:bg-muted\",\n        secondary:\n          \"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary/80\",\n        ghost:\n          \"text-muted-foreground hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground\",\n      },\n      size: {\n        default: \"h-11 px-5 py-2\",\n        sm: \"h-9 px-3\",\n        lg: \"h-12 px-6\",\n        icon: \"size-11\",\n      },\n    },\n    defaultVariants: {\n      variant: \"default\",\n      size: \"default\",\n    },\n  },\n);\n\ntype Refusable = { preventDefault: () => void; preventBaseUIHandler: () => void };\n\nfunction refuse(event: Refusable): void {\n  event.preventDefault();\n  event.preventBaseUIHandler();\n}\n\nfunction unavailable(native: boolean) {\n  return {\n    disabled: native ? true : undefined,\n    \"aria-disabled\": native ? undefined : true,\n    onClick: (event: MouseEvent & Refusable) => refuse(event),\n    onKeyDown: (event: KeyboardEvent & Refusable) => {\n      if (event.key === \"Enter\" || event.key === \" \") {\n        refuse(event);\n      }\n    },\n  };\n}\n\nfunction Button({\n  className,\n  variant,\n  size,\n  render,\n  loading = false,\n  disabled,\n  children,\n  ...props\n}: useRender.ComponentProps<\"button\"> &\n  VariantProps<typeof buttonVariants> & { loading?: boolean }) {\n  const target = isValidElement<{ children?: ReactNode; ref?: Ref<Element> }>(render)\n    ? render\n    : undefined;\n  const { children: targetChildren, ref: targetRef, ...targetProps } = target?.props ?? {};\n  const label = targetChildren ?? children;\n  const native = render === undefined || target?.type === \"button\";\n  const blocked = loading || Boolean(disabled);\n  const ownProps = {\n    \"data-slot\": \"button\",\n    className: cn(buttonVariants({ variant, size, className })),\n    \"aria-busy\": loading ? true : undefined,\n    children: loading ? (\n      <>\n        <span className=\"inline-flex items-center gap-2 opacity-0\">{label}</span>\n        <span className=\"absolute inset-0 flex items-center justify-center\">\n          <Spinner />\n        </span>\n      </>\n    ) : (\n      label\n    ),\n  };\n\n  return useRender({\n    defaultTagName: \"button\",\n    render: target\n      ? (createElement(target.type, { key: target.key, ref: targetRef }) as ReactElement)\n      : render,\n    props: mergeProps<\"button\">(\n      ownProps,\n      props,\n      targetProps,\n      blocked ? unavailable(native) : undefined,\n    ),\n  });\n}\n\nexport { Button, buttonVariants };\n",
      "type": "registry:ui",
      "target": "components/ui/button.tsx"
    }
  ],
  "type": "registry:ui"
}