{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "button",
  "type": "registry:ui",
  "title": "Button",
  "description": "The Kura button: six variants, four sizes, loading state, asChild, tactile press and a signal focus ring.",
  "dependencies": [
    "radix-ui"
  ],
  "registryDependencies": [
    "https://kuro.abstergo.fyi/r/kura-theme.json",
    "https://kuro.abstergo.fyi/r/spinner.json",
    "utils"
  ],
  "files": [
    {
      "path": "registry/kura/button/button.tsx",
      "type": "registry:ui",
      "target": "components/kura/button/button.tsx",
      "content": "import { Slot } from \"radix-ui\";\nimport type * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport { Spinner } from \"@/components/kura/spinner\";\n\nexport type ButtonVariant = \"primary\" | \"secondary\" | \"ghost\" | \"outline\" | \"accent\" | \"danger\";\nexport type ButtonSize = \"xs\" | \"sm\" | \"md\" | \"lg\";\n\nexport interface ButtonProps extends React.ComponentProps<\"button\"> {\n  /** `primary` = ink (default call to action); `accent` = the AI signal colour, use at most once per view. */\n  variant?: ButtonVariant;\n  size?: ButtonSize;\n  /** Shows a spinner, sets `aria-busy` and disables interaction while keeping the width stable. */\n  loading?: boolean;\n  /** Render the child element instead of a <button> (e.g. a Next.js <Link>). */\n  asChild?: boolean;\n}\n\nconst base =\n  \"relative inline-flex shrink-0 cursor-pointer select-none items-center justify-center gap-1.5 whitespace-nowrap font-medium font-kura-sans outline-none \" +\n  \"transition-[background-color,color,box-shadow,transform,opacity] duration-(--kura-duration-fast) ease-kura-out \" +\n  \"focus-visible:shadow-kura-focus active:not-disabled:scale-[0.97] motion-reduce:active:not-disabled:scale-100 \" +\n  \"disabled:cursor-not-allowed disabled:opacity-50 aria-busy:cursor-progress \" +\n  \"[&_svg]:pointer-events-none [&_svg]:shrink-0\";\n\nconst variants: Record<ButtonVariant, string> = {\n  primary: \"bg-kura-ink text-kura-fg-inverted shadow-kura-xs hover:not-disabled:bg-kura-ink-hover\",\n  secondary:\n    \"bg-kura-surface text-kura-fg shadow-kura-sm hover:not-disabled:bg-kura-surface-sunken\",\n  outline:\n    \"bg-transparent text-kura-fg shadow-[inset_0_0_0_1px_var(--kura-border-strong)] hover:not-disabled:bg-kura-hover\",\n  ghost:\n    \"bg-transparent text-kura-fg-muted hover:not-disabled:bg-kura-hover hover:not-disabled:text-kura-fg\",\n  accent:\n    \"bg-kura-accent text-kura-accent-fg shadow-kura-xs hover:not-disabled:bg-kura-accent-hover\",\n  danger: \"bg-kura-danger text-white shadow-kura-xs hover:not-disabled:opacity-90\",\n};\n\nconst sizes: Record<ButtonSize, string> = {\n  xs: \"h-6 rounded-kura-sm px-2 text-xs [&_svg:not([class*='size-'])]:size-3\",\n  sm: \"h-7 rounded-kura-sm px-2.5 text-[13px] [&_svg:not([class*='size-'])]:size-3.5\",\n  md: \"h-8 rounded-kura-md px-3 text-sm [&_svg:not([class*='size-'])]:size-4\",\n  lg: \"h-10 rounded-kura-lg px-4 text-[15px] [&_svg:not([class*='size-'])]:size-4\",\n};\n\n/** Class string for a button look, for elements that cannot use <Button> directly. */\nexport function buttonVariants({\n  variant = \"primary\",\n  size = \"md\",\n  className,\n}: {\n  variant?: ButtonVariant;\n  size?: ButtonSize;\n  className?: string;\n} = {}): string {\n  return cn(base, variants[variant], sizes[size], className);\n}\n\n/**\n * The Kura button. Press feedback is a 0.97 scale on :active (disabled under reduced motion),\n * focus is a 2px signal ring outside a 1px canvas gap.\n */\nexport function Button({\n  variant = \"primary\",\n  size = \"md\",\n  loading = false,\n  asChild = false,\n  disabled,\n  className,\n  children,\n  type,\n  ...props\n}: ButtonProps) {\n  const Comp = asChild ? Slot.Root : \"button\";\n  return (\n    <Comp\n      data-slot=\"button\"\n      data-variant={variant}\n      data-size={size}\n      type={asChild ? type : (type ?? \"button\")}\n      disabled={disabled || loading}\n      aria-busy={loading || undefined}\n      className={buttonVariants({ variant, size, className })}\n      {...props}\n    >\n      {asChild ? (\n        children\n      ) : (\n        <>\n          {loading && (\n            <span className=\"absolute inset-0 flex items-center justify-center\">\n              <Spinner size={size === \"lg\" ? \"md\" : \"sm\"} label={null} />\n            </span>\n          )}\n          {loading ? (\n            <span className=\"invisible inline-flex items-center gap-1.5\">{children}</span>\n          ) : (\n            children\n          )}\n        </>\n      )}\n    </Comp>\n  );\n}\n"
    },
    {
      "path": "registry/kura/button/index.ts",
      "type": "registry:ui",
      "target": "components/kura/button/index.ts",
      "content": "export {\n  Button,\n  type ButtonProps,\n  type ButtonSize,\n  type ButtonVariant,\n  buttonVariants,\n} from \"./button\";\n"
    }
  ],
  "categories": [
    "primitives",
    "button",
    "action",
    "cta",
    "submit"
  ],
  "docs": "Docs: https://kuro.abstergo.fyi/components/button · Markdown for agents: https://kuro.abstergo.fyi/components/button.md",
  "meta": {
    "kura": {
      "status": "stable",
      "whenToUse": [
        "Any clickable action: submit, confirm, cancel, open.",
        "Links that should look like buttons (use asChild with your router's Link)."
      ],
      "whenNotToUse": [
        "Icon-only actions — use icon-button (it enforces an accessible label and adds a tooltip).",
        "Approve/deny decisions for agent actions — use approval-prompt."
      ]
    }
  }
}
