Patch UI

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

PropTypeDefaultDescription
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.
iconReactNode-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.
loadingbooleanfalseShows a spinner and disables the button.
disabledbooleanfalseDisables the button, preventing interaction.
renderRenderProp<'button'>-Polymorphic render prop - pass a different element (e.g. <a>) to change the rendered tag while keeping button styles.
classNamestring-Additional CSS classes to apply.
childrenReactNode-The button label content.

Notes

  • Polymorphic rendering: Use the render prop 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 icon without children to create a square icon button. The size adjusts automatically.
  • Loading state: When loading is 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.