{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "button",
  "type": "registry:ui",
  "title": "Button",
  "description": "A button built on Base UI, with Facade styles. Every size is at least 44 by 44 pixels.",
  "categories": [
    "atom"
  ],
  "dependencies": [
    "@base-ui-components/react@1.0.0-rc.0",
    "class-variance-authority@^0.7.1",
    "lucide-react@^1.47.0"
  ],
  "registryDependencies": [
    "https://facadeui.dev/r/utils.json"
  ],
  "files": [
    {
      "path": "src/ui/button.tsx",
      "type": "registry:ui",
      "target": "components/ui/button.tsx",
      "content": "/**\n * Button — Facade styling over Base UI's `Button`.\n *\n * Not marked `\"use client\"`, and deliberately so: Base UI's own modules carry the\n * directive, so this wrapper stays a server component and a hero rendered on the\n * server ships no extra client boundary of its own.\n *\n * `render` is Base UI's composition escape hatch (the equivalent of Radix's\n * `asChild`). Use it to turn the button into a *non-button* control that should\n * still behave like one, and pass `nativeButton={false}` so Base UI supplies the\n * `role=\"button\"`, `tabindex` and Space/Enter handling that element lacks:\n *\n *   <Button render={<span />} nativeButton={false}>Toggle</Button>\n *\n * Do not use `render` for links. Two things go wrong, both verified against\n * Base UI 1.0.0-rc.0 in `button.test.tsx`:\n *\n *   - with `nativeButton` left at its default, the anchor is emitted with\n *     `type=\"button\"` and, when disabled, a `disabled` attribute — neither is\n *     valid on `<a>`, and `disabled` does not actually prevent navigation;\n *   - with `nativeButton={false}`, the anchor gets `role=\"button\"`, so a control\n *     that navigates is announced as one that acts.\n *\n * Style the link directly instead — that is what `buttonVariants` is for, and\n * what `CtaGroup` does:\n *\n *   <a href=\"/pricing\" className={buttonVariants({ variant: \"outline\" })}>…</a>\n *\n * a11y: every size is at least 44x44 CSS px (WCAG 2.5.5), the focus ring is\n * always visible, and `loading` sets `aria-busy` while keeping the label in the\n * accessible name so it never changes mid-interaction.\n *\n * Dependencies: @base-ui-components/react, class-variance-authority,\n * lucide-react, react, @/lib/utils.\n */\n\nimport {\n  Button as BaseButton,\n  type ButtonProps as BaseButtonProps,\n} from \"@base-ui-components/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Loader2Icon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport const buttonVariants = cva(\n  [\n    \"inline-flex shrink-0 items-center justify-center gap-2 whitespace-nowrap\",\n    \"rounded-md font-medium\",\n    \"duration-facade-fast ease-facade-out transition-[color,background-color,border-color,box-shadow,opacity]\",\n    \"focus-visible:ring-ring focus-visible:ring-offset-background outline-none focus-visible:ring-2 focus-visible:ring-offset-2\",\n    \"disabled:pointer-events-none disabled:opacity-50\",\n    \"aria-disabled:pointer-events-none aria-disabled:opacity-50\",\n    \"[&_svg:not([class*='size-'])]:size-5 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n  ],\n  {\n    variants: {\n      variant: {\n        primary: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n        secondary: \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n        outline:\n          \"border-border bg-background text-foreground hover:bg-accent hover:text-accent-foreground border\",\n        ghost: \"text-foreground hover:bg-accent hover:text-accent-foreground\",\n        link: \"text-foreground hover:text-foreground/80 underline underline-offset-4\",\n        destructive: \"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\n      },\n      size: {\n        /** 44px — the WCAG 2.5.5 target minimum, and the floor for every control. */\n        sm: \"h-11 px-4 text-sm\",\n        md: \"h-12 px-5 text-base\",\n        lg: \"h-14 px-7 text-base sm:text-lg\",\n        icon: \"size-11 p-0\",\n      },\n      fullWidth: { true: \"w-full\", false: \"\" },\n    },\n    defaultVariants: { variant: \"primary\", size: \"md\", fullWidth: false },\n  },\n)\n\nexport type ButtonVariantProps = VariantProps<typeof buttonVariants>\n\nexport type ButtonProps = BaseButtonProps &\n  ButtonVariantProps & {\n    /** Shows a spinner, sets `aria-busy`, and stops the button from being activated. */\n    loading?: boolean\n    /** Status text for screen readers, announced with the spinner. */\n    loadingLabel?: string\n  }\n\nexport function Button({\n  variant,\n  size,\n  fullWidth,\n  loading = false,\n  loadingLabel = \"Loading\",\n  className,\n  disabled,\n  children,\n  ...props\n}: ButtonProps) {\n  return (\n    <BaseButton\n      {...props}\n      disabled={disabled === true || loading}\n      aria-busy={loading || undefined}\n      className={cn(buttonVariants({ variant, size, fullWidth }), className)}\n    >\n      {loading ? (\n        <>\n          <Loader2Icon aria-hidden className=\"animate-spin\" />\n          <span className=\"sr-only\">{loadingLabel}</span>\n        </>\n      ) : null}\n      {children}\n    </BaseButton>\n  )\n}\n"
    }
  ],
  "docs": "Import styles/facade-tokens.css in your global stylesheet, after @import \"tailwindcss\". Docs: https://facadeui.dev/components/button"
}
