Button
A polymorphic button component with multiple variants, sizes, icon support, and loading state.
$npx shadcn add @patchui/button
Variants
Sizes
With Icons
Apply with arrow
States
Usage
import { Button } from "@patchui/react";
// Basic
<Button variant="primary">Click me</Button>
// With icon
<Button icon={<Mail className="h-4 w-4" />}>Send Email</Button>
// Icon only
<Button variant="secondary" icon={<Download className="h-4 w-4" />} />
// Trailing arrow (apply pattern)
<Button
variant="primary"
icon={<ArrowRight className="h-4 w-4" />}
iconPosition="right"
>
Apply now
</Button>
// Loading state
<Button loading>Saving...</Button>
// As a link (polymorphic render prop)
<Button render={<a href="/dashboard" />}>Go to Dashboard</Button>Props
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "primary" | "secondary" | "outline" | "ghost" | "danger" | "link" | "uppercase" | "primary" | The visual style of the button. |
| size | "sm" | "md" | "lg" | "md" | The size of the button. |
| icon | ReactNode | - | An icon element to render alongside the button text. When passed without children, renders as an icon-only button. |
| iconPosition | "left" | "right" | "left" | Which side of the label the icon appears on. |
| loading | boolean | false | Shows a spinner and disables the button. |
| disabled | boolean | false | Disables the button, preventing interaction. |
| render | RenderProp<'button'> | - | Polymorphic render prop - pass a different element (e.g. <a>) to change the rendered tag while keeping button styles. |
| className | string | - | Additional CSS classes to apply. |
| children | ReactNode | - | The button label content. |
Notes
- Polymorphic rendering: Use the
renderprop to render the button as any HTML element. For example,render={<a href="/page" />}renders an anchor tag with button styling. - Icon-only buttons: Pass an
iconwithoutchildrento create a square icon button. The size adjusts automatically. - Loading state: When
loadingis true, the button content is replaced with a spinner and the button is disabled to prevent double-submission. - Touch targets: All sizes include a minimum 44×44px touch target via a pseudo-element for accessibility on touch devices.