{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "button",
  "title": "Button",
  "description": "Button with default, outline, secondary, ghost, destructive and link variants, sm, default and lg sizes plus icon sizes; renders as a link or another element with `render`.",
  "dependencies": [
    "@base-ui/react@^1.8.0",
    "class-variance-authority@^0.7.1"
  ],
  "files": [
    {
      "path": "registry/rapid/ui/button/button.tsx",
      "content": "import { Button as ButtonPrimitive } from '@base-ui/react/button'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport * as React from 'react'\nimport { cn } from '@/lib/utils'\n\nconst buttonVariants = cva(\n\t\"group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring cursor-pointer disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 data-disabled:cursor-not-allowed data-disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n\t{\n\t\tvariants: {\n\t\t\tvariant: {\n\t\t\t\t// Colours kept from the previous Rapid button (ghost is shadcn's), with a pressed background instead of\n\t\t\t\t// shadcn's press-down nudge; sizes, focus and states are shadcn's\n\t\t\t\tdefault: 'bg-primary text-primary-foreground hover:bg-primary/90 active:bg-primary/80',\n\t\t\t\toutline:\n\t\t\t\t\t'border-input bg-background text-foreground hover:bg-accent active:bg-[color-mix(in_oklch,var(--accent),var(--foreground)_6%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground',\n\t\t\t\tsecondary:\n\t\t\t\t\t'bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--secondary-foreground)_8%)] active:bg-[color-mix(in_oklch,var(--secondary),var(--secondary-foreground)_16%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground',\n\t\t\t\tghost:\n\t\t\t\t\t'hover:bg-muted hover:text-foreground active:bg-[color-mix(in_oklch,var(--muted),var(--foreground)_10%)] aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50',\n\t\t\t\tdestructive: 'bg-destructive text-white hover:bg-destructive/90 active:bg-destructive/80',\n\t\t\t\t// Quiet at rest so a delete sits at the same weight as the actions beside it; the destructive colour arrives on\n\t\t\t\t// hover and focus, where the intent is real\n\t\t\t\t'ghost-destructive':\n\t\t\t\t\t'hover:bg-destructive/10 hover:text-[color-mix(in_oklab,var(--destructive)_80%,black)] focus-visible:text-[color-mix(in_oklab,var(--destructive)_80%,black)] active:bg-destructive/20 aria-expanded:bg-destructive/10 aria-expanded:text-destructive dark:hover:bg-destructive/20 dark:hover:text-[color-mix(in_oklab,var(--destructive)_50%,white)] dark:focus-visible:text-[color-mix(in_oklab,var(--destructive)_50%,white)]',\n\t\t\t\tlink: 'text-primary underline underline-offset-4',\n\t\t\t},\n\t\t\tsize: {\n\t\t\t\tdefault: 'h-10 gap-2 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3',\n\t\t\t\txs: \"h-8 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n\t\t\t\tsm: \"h-8 gap-1.5 rounded-[min(var(--radius-md),12px)] px-3 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n\t\t\t\tlg: 'h-12 gap-2 px-6 has-data-[icon=inline-end]:pr-5 has-data-[icon=inline-start]:pl-5',\n\t\t\t\ticon: 'size-10',\n\t\t\t\t'icon-xs':\n\t\t\t\t\t\"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3\",\n\t\t\t\t'icon-sm': 'size-8 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg',\n\t\t\t\t'icon-lg': 'size-12',\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tvariant: 'default',\n\t\t\tsize: 'default',\n\t\t},\n\t},\n)\n\n// Base UI's Button defaults to type=\"button\" on a native <button>, so buttons never submit a form by accident.\n// Render a link with `render={<a href=\"…\" />}` and `nativeButton={false}`. Base UI would give it role=\"button\"; we drop\n// that role for <a> elements so a link keeps its link semantics.\nfunction Button({\n\tclassName,\n\tvariant = 'default',\n\tsize = 'default',\n\trender,\n\t...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n\tconst isLink = React.isValidElement(render) && render.type === 'a' && !('role' in props)\n\n\treturn (\n\t\t<ButtonPrimitive\n\t\t\tdata-slot=\"button\"\n\t\t\tdata-variant={variant}\n\t\t\tdata-size={size}\n\t\t\tclassName={cn(buttonVariants({ variant, size, className }))}\n\t\t\trender={render}\n\t\t\t{...(isLink ? { role: undefined } : null)}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\n\nexport { Button, buttonVariants }\n",
      "type": "registry:ui",
      "target": "components/ui/button.tsx"
    }
  ],
  "type": "registry:ui"
}