button
A customizable button component for triggering actions in your application.
Features
- Multiple styles, sizes, and border options out of the box
- Built-in loading state with spinner and auto-disable
- Supports icons, dual icons, and collapsed icon-only mode
- Flexible
asChildrendering for links and custom wrappers - Smooth hover animations with optional
AnimationIcon - Fully typed, accessible, and responsive
- Powered by
@gentleduck/variantsfor scalable theming - Clean, composable, and Tailwind-optimized
Philosophy
Buttons are the primary call to action in any interface. We ship an intentionally rich variant system because buttons carry the most visual weight in UI decisions — primary, destructive, ghost, and outline each communicate different levels of commitment. The asChild pattern lets you render any element as a button, because sometimes a link needs to look like one.
How It's Built
Installation
npx @gentleduck/cli add button
npx @gentleduck/cli add button
Usage
import { Button } from '@/components/ui/button'import { Button } from '@/components/ui/button'<Button>Button</Button><Button>Button</Button>Button
Button is a versatile and customizable React component designed to render a button with various styles and functionalities. It supports different sizes, variants, and additional features like loading states and icons. The component is flexible and can be used in a variety of scenarios, from simple buttons to complex interactive elements.
Example Usage:
import { Button } from '@/components/ui/button'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
const MyButton = () => {
return (
<Tooltip>
<TooltipTrigger asChild>
<Button size="lg" variant="default">
Submit
</Button>
</TooltipTrigger>
<TooltipContent>Submit Button</TooltipContent>
</Tooltip>
)
}import { Button } from '@/components/ui/button'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
const MyButton = () => {
return (
<Tooltip>
<TooltipTrigger asChild>
<Button size="lg" variant="default">
Submit
</Button>
</TooltipTrigger>
<TooltipContent>Submit Button</TooltipContent>
</Tooltip>
)
}Link
You can use the buttonVariants helper to create a any element like a link that looks like a button.
import { buttonVariants } from '@/components/ui/button'import { buttonVariants } from '@/components/ui/button'<Link className={buttonVariants({ variant: 'outline' })}>I'm a Link 🦆</Link><Link className={buttonVariants({ variant: 'outline' })}>I'm a Link 🦆</Link>Alternatively, you can set the asChild parameter and nest the link component.
<Button asChild>
<Link href="/tos">I'm a Link to ToS 🦆</Link>
</Button><Button asChild>
<Link href="/tos">I'm a Link to ToS 🦆</Link>
</Button>Examples
Primary
Secondary
Ghost
Outline
Link
Destructive
Warning
Dashed
Nothing
With Border
With Border Destructive
With Border Warning
With Border Secondary
With Icon
Loading
When loading is true, Button renders a lucide-react <Loader /> with animate-spin, disables interaction, and replaces the leading icon until loading completes.
With Second Icon
Collapsible
Expand Icon
RTL
API Reference
Button Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'default' | 'destructive' | 'warning' | 'outline' | 'dashed' | 'secondary' | 'ghost' | 'link' | 'expand_icon' | 'nothing' | 'default' | Visual style variant |
size | 'default' | 'sm' | 'lg' | 'icon' | 'icon-sm' | 'icon-lg' | 'default' | Size of the button |
border | 'default' | 'primary' | 'secondary' | 'destructive' | 'warning' | 'default' | Border style variant |
asChild | boolean | -- | If true, renders using a custom child element via Slot (e.g. a Link) |
loading | boolean | -- | If true, renders <Loader className="animate-spin" />, disables the button, and temporarily overrides icon |
disabled | boolean | -- | Disables the button manually |
icon | React.ReactNode | -- | Primary icon displayed before the content (or centered if collapsed) |
secondIcon | React.ReactNode | -- | Secondary icon displayed after the content |
isCollapsed | boolean | -- | If true, renders icon-only button (hides children and secondIcon) |
type | 'button' | 'submit' | 'reset' | 'button' | Native HTML button type |
...props | Omit<React.HTMLProps<HTMLButtonElement>, 'size'> | -- | Additional props to spread to the button element |
AnimationIcon Props
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | (required) | Content inside the animation icon wrapper |
animationIcon | { icon?: React.ReactNode; iconPlacement?: 'left' | 'right' } | -- | Animation icon configuration with icon element and placement direction |