{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "button",
  "title": "Button",
  "description": "Button with a full variant x tone x size matrix: 5 variants (solid, soft, outline, ghost, link), 6 tones (neutral, brand, success, warning, danger, info), 10 sizes (xs-xl plus square icon-xs through icon-xl for icon-only buttons), plus isLoading and asChild. Every tone is driven by ai2 semantic tokens.",
  "dependencies": [
    "class-variance-authority@^0.7.1",
    "radix-ui@^1.6.1",
    "lucide-react@^1.23.0"
  ],
  "registryDependencies": [
    "@ai2/tokens",
    "@ai2/primitives"
  ],
  "files": [
    {
      "path": "registry/ai2/ui/button.tsx",
      "content": "\"use client\"\n\nimport type * as React from \"react\"\nimport { Slot } from \"@/registry/ai2/ui/primitives\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Loader2 } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n  \"inline-flex shrink-0 items-center justify-center whitespace-nowrap font-medium outline-none transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-danger aria-invalid:ring-danger/20 dark:aria-invalid:ring-danger/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_i]:pointer-events-none [&_i]:shrink-0 [&_i]:text-base [&_i]:leading-none\",\n  {\n    variants: {\n      variant: {\n        solid: \"\",\n        soft: \"\",\n        outline: \"border bg-transparent\",\n        ghost: \"bg-transparent\",\n        link: \"bg-transparent underline-offset-4 hover:underline\",\n      },\n      tone: {\n        neutral: \"\",\n        brand: \"\",\n        success: \"\",\n        warning: \"\",\n        danger: \"\",\n        info: \"\",\n      },\n      size: {\n        xs: \"h-7 gap-1 rounded-md px-2.5 text-xs\",\n        sm: \"h-8 gap-1.5 rounded-md px-3 text-sm\",\n        md: \"h-9 gap-2 rounded-lg px-4 text-sm\",\n        lg: \"h-10 gap-2 rounded-lg px-5 text-sm\",\n        xl: \"h-12 gap-2.5 rounded-xl px-6 text-base\",\n        \"icon-xs\": \"size-7 rounded-md text-xs\",\n        \"icon-sm\": \"size-8 rounded-md text-sm\",\n        icon: \"size-9 rounded-lg text-sm\",\n        \"icon-lg\": \"size-10 rounded-lg text-sm\",\n        \"icon-xl\": \"size-12 rounded-xl text-base\",\n      },\n    },\n    compoundVariants: [\n      { variant: \"solid\", tone: \"neutral\", class: \"bg-primary text-primary-foreground hover:bg-primary/90\" },\n      { variant: \"solid\", tone: \"brand\", class: \"bg-brand text-brand-foreground hover:bg-brand/90\" },\n      { variant: \"solid\", tone: \"success\", class: \"bg-success text-success-foreground hover:bg-success/90\" },\n      { variant: \"solid\", tone: \"warning\", class: \"bg-warning text-warning-foreground hover:bg-warning/90\" },\n      { variant: \"solid\", tone: \"danger\", class: \"bg-danger text-danger-foreground hover:bg-danger/90\" },\n      { variant: \"solid\", tone: \"info\", class: \"bg-info text-info-foreground hover:bg-info/90\" },\n      { variant: \"soft\", tone: \"neutral\", class: \"bg-secondary text-secondary-foreground hover:bg-secondary/80\" },\n      { variant: \"soft\", tone: \"brand\", class: \"bg-brand-soft text-brand-soft-foreground hover:bg-brand-soft/80\" },\n      { variant: \"soft\", tone: \"success\", class: \"bg-success-soft text-success-soft-foreground hover:bg-success-soft/80\" },\n      { variant: \"soft\", tone: \"warning\", class: \"bg-warning-soft text-warning-soft-foreground hover:bg-warning-soft/80\" },\n      { variant: \"soft\", tone: \"danger\", class: \"bg-danger-soft text-danger-soft-foreground hover:bg-danger-soft/80\" },\n      { variant: \"soft\", tone: \"info\", class: \"bg-info-soft text-info-soft-foreground hover:bg-info-soft/80\" },\n      { variant: \"outline\", tone: \"neutral\", class: \"border-border text-foreground hover:bg-accent hover:text-accent-foreground\" },\n      { variant: \"outline\", tone: \"brand\", class: \"border-brand/40 text-brand hover:bg-brand-soft\" },\n      { variant: \"outline\", tone: \"success\", class: \"border-success/40 text-success hover:bg-success-soft\" },\n      { variant: \"outline\", tone: \"warning\", class: \"border-warning/50 text-warning-soft-foreground hover:bg-warning-soft\" },\n      { variant: \"outline\", tone: \"danger\", class: \"border-danger/40 text-danger hover:bg-danger-soft\" },\n      { variant: \"outline\", tone: \"info\", class: \"border-info/40 text-info hover:bg-info-soft\" },\n      { variant: \"ghost\", tone: \"neutral\", class: \"text-foreground hover:bg-accent hover:text-accent-foreground\" },\n      { variant: \"ghost\", tone: \"brand\", class: \"text-brand hover:bg-brand-soft\" },\n      { variant: \"ghost\", tone: \"success\", class: \"text-success hover:bg-success-soft\" },\n      { variant: \"ghost\", tone: \"warning\", class: \"text-warning-soft-foreground hover:bg-warning-soft\" },\n      { variant: \"ghost\", tone: \"danger\", class: \"text-danger hover:bg-danger-soft\" },\n      { variant: \"ghost\", tone: \"info\", class: \"text-info hover:bg-info-soft\" },\n      { variant: \"link\", tone: \"neutral\", class: \"text-foreground\" },\n      { variant: \"link\", tone: \"brand\", class: \"text-brand\" },\n      { variant: \"link\", tone: \"success\", class: \"text-success\" },\n      { variant: \"link\", tone: \"warning\", class: \"text-warning-soft-foreground\" },\n      { variant: \"link\", tone: \"danger\", class: \"text-danger\" },\n      { variant: \"link\", tone: \"info\", class: \"text-info\" },\n    ],\n    defaultVariants: {\n      variant: \"solid\",\n      tone: \"neutral\",\n      size: \"md\",\n    },\n  }\n)\n\ninterface ButtonProps\n  extends React.ComponentProps<\"button\">,\n    VariantProps<typeof buttonVariants> {\n  asChild?: boolean\n  isLoading?: boolean\n}\n\nfunction Button({\n  className,\n  variant,\n  tone,\n  size,\n  asChild = false,\n  isLoading = false,\n  disabled,\n  children,\n  ...props\n}: ButtonProps) {\n  const Comp = asChild ? Slot.Root : \"button\"\n\n  return (\n    <Comp\n      data-slot=\"button\"\n      data-variant={variant ?? \"solid\"}\n      data-tone={tone ?? \"neutral\"}\n      className={cn(buttonVariants({ variant, tone, size, className }))}\n      disabled={disabled || isLoading}\n      aria-busy={isLoading || undefined}\n      {...props}\n    >\n      {asChild ? (\n        children\n      ) : (\n        <>\n          {isLoading && <Loader2 aria-hidden=\"true\" className=\"animate-spin\" />}\n          {children}\n        </>\n      )}\n    </Comp>\n  )\n}\n\nexport { Button, buttonVariants, type ButtonProps }\n",
      "type": "registry:ui"
    }
  ],
  "docs": "Use tone for semantic intent (brand for primary product actions, danger for destructive) and variant for visual weight. isLoading disables the button and shows a spinner.",
  "categories": [
    "form",
    "actions"
  ],
  "type": "registry:ui"
}