Button
Versatile button component with multiple variants, sizes, loading state, and asChild pattern.
Overview
The Button component from packages/ui provides a consistent button style across the entire application. It supports multiple visual variants, sizes, a loading state, and the asChild pattern for rendering as different elements.
Import
import { Button } from "@saas/ui";Variants
The variant prop controls the visual style:
<Button variant="default">Primary</Button>
<Button variant="outline">Outline</Button>
<Button variant="destructive">Delete</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
<Button variant="secondary">Secondary</Button>| Variant | Appearance |
|---|---|
default | Solid indigo background with white text |
outline | Transparent with a border |
destructive | Red background for dangerous actions |
ghost | No background, subtle hover effect |
link | Styled as an underlined text link |
secondary | Light gray background |
Sizes
The size prop controls dimensions and padding:
<Button size="sm">Small</Button>
<Button size="default">Default</Button>
<Button size="lg">Large</Button>
<Button size="icon">
<TrashIcon className="h-4 w-4" />
</Button>| Size | Use case |
|---|---|
sm | Compact actions, table rows |
default | Standard buttons |
lg | Hero CTAs, prominent actions |
icon | Square button for icon-only actions |
Loading State
Pass disabled along with a spinner to indicate loading:
<Button disabled>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Saving...
</Button>The button is automatically non-interactive when disabled is set.
asChild Pattern
Use the asChild prop to render the button styles on a different element (e.g., a Next.js Link):
import Link from "next/link";
<Button asChild>
<Link href="/dashboard">Go to Dashboard</Link>
</Button>This merges the button's classes onto the child element without adding an extra <button> wrapper.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "default" | "outline" | "destructive" | "ghost" | "link" | "secondary" | "default" | Visual style |
size | "sm" | "default" | "lg" | "icon" | "default" | Button dimensions |
asChild | boolean | false | Render as child element |
disabled | boolean | false | Disable interaction |
className | string | — | Additional CSS classes |
All standard <button> HTML attributes are also accepted.
Tips
- Use
destructivevariant only for irreversible actions (delete, remove). - Pair
ghostvariant with icon-only buttons in toolbars. - Always provide visible text or an
aria-labelfor icon-only buttons.
Done reading? Mark this page as complete.