Components
Button
A compound button component with variants, modes, sizes, and polymorphic icon support.
Installation
bunx @happlyui/cli@latest add button
Dependencies
npm packages
@radix-ui/react-slot
Registry dependencies
These are automatically installed when you add this component.
tvpolymorphicrecursive-clone-childrenloader
Usage
import * as Button from "@/components/ui/button"
<Button.Root variant="primary" mode="filled">
<Button.Icon as={MailIcon} />
Send Email
</Button.Root>
Examples
Primary Variant
The primary variant uses the brand color for main call-to-action buttons.
<Button.Root variant="primary" mode="filled">Get Started</Button.Root>
<Button.Root variant="primary" mode="stroke">Get Started</Button.Root>
<Button.Root variant="primary" mode="lighter">Get Started</Button.Root>
<Button.Root variant="primary" mode="ghost">Get Started</Button.Root>
Neutral Variant
The neutral variant uses grayscale colors for secondary actions.
<Button.Root variant="neutral" mode="filled">Learn More</Button.Root>
<Button.Root variant="neutral" mode="stroke">Learn More</Button.Root>
<Button.Root variant="neutral" mode="lighter">Learn More</Button.Root>
<Button.Root variant="neutral" mode="ghost">Learn More</Button.Root>
Success Variant
The success variant for positive or confirmation actions.
<Button.Root variant="success" mode="filled">Try Again</Button.Root>
<Button.Root variant="success" mode="stroke">Try Again</Button.Root>
<Button.Root variant="success" mode="lighter">Try Again</Button.Root>
<Button.Root variant="success" mode="ghost">Try Again</Button.Root>
Warning Variant
The warning variant for cautionary actions.
<Button.Root variant="warning" mode="filled">Try Again</Button.Root>
<Button.Root variant="warning" mode="stroke">Try Again</Button.Root>
<Button.Root variant="warning" mode="lighter">Try Again</Button.Root>
<Button.Root variant="warning" mode="ghost">Try Again</Button.Root>
Error Variant
The error variant for destructive actions.
<Button.Root variant="error" mode="filled">Try Again</Button.Root>
<Button.Root variant="error" mode="stroke">Try Again</Button.Root>
<Button.Root variant="error" mode="lighter">Try Again</Button.Root>
<Button.Root variant="error" mode="ghost">Try Again</Button.Root>
Sizes
Buttons come in multiple sizes across all modes.
<Button.Root size="medium">Medium</Button.Root>
<Button.Root size="small">Small</Button.Root>
<Button.Root size="xsmall">Xsmall</Button.Root>
<Button.Root size="xxsmall">Xxsmall</Button.Root>
Disabled
Disabled buttons across all modes.
<Button.Root disabled>Disabled</Button.Root>
<Button.Root mode="stroke" disabled>Disabled</Button.Root>
With Icon
Use Button.Icon with the `as` prop for polymorphic icon rendering.
<Button.Root>
Button
<Button.Icon as={RiArrowRightSLine} />
</Button.Root>
<Button.Root>
<Button.Icon as={RiFileCopyLine} />
</Button.Root>
Full Width
Buttons can stretch to fill their container with a className override.
<Button.Root variant="neutral" className="w-full">
Learn More
</Button.Root>
As Child
Use the asChild prop with Radix Slot to render as a different element, such as a link.
<Button.Root asChild>
<a href="#">As link</a>
</Button.Root>
Loading
Use the loading prop to trigger an animated transition. The original text wave-blurs out letter by letter, then a spinner and "Loading..." wave-blurs in with a continuous typewriter dot effect.
<Button.Root loading>Get Started</Button.Root>
Loading Interactive
Click the button to see the full loading animation in action. The state resets after 3 seconds.
<Button.Root loading={loading} onClick={handleClick}>
Get Started
</Button.Root>
Composed
Simplified usage via the Composed wrapper with leadingIcon and trailingIcon props.
<Button.Composed
leadingIcon={RiArrowLeftSLine}
trailingIcon={RiArrowRightSLine}
variant="neutral"
mode="stroke"
>
Button
</Button.Composed>
API Reference
Button.Root
The main button component.
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'primary' | 'neutral' | 'error' | 'warning' | 'success' | 'primary' | The color variant |
mode | 'filled' | 'stroke' | 'lighter' | 'ghost' | 'filled' | The visual style |
size | 'medium' | 'small' | 'xsmall' | 'xxsmall' | 'medium' | The size of the button |
asChild | boolean | false | Renders as child element using Radix Slot |
loading | boolean | false | Triggers an animated loading transition with a wave text effect, spinner, and typewriter dots |
loadingText | string | 'Loading' | Override the loading text displayed during the loading animation. The '...' dots are appended automatically. |
disabled | boolean | false | Disables the button |
Button.Icon
Polymorphic icon container that receives variant props from Button.Root.
| Prop | Type | Default | Description |
|---|---|---|---|
as | React.ElementType | 'div' | The element or component to render as |
Button.Composed
A simplified wrapper that composes Root and Icon into a single component.
| Prop | Type | Default | Description |
|---|---|---|---|
leadingIcon | React.ElementType | - | Icon rendered before the children |
trailingIcon | React.ElementType | - | Icon rendered after the children |
variant | 'primary' | 'neutral' | 'error' | 'warning' | 'success' | 'primary' | The color variant |
mode | 'filled' | 'stroke' | 'lighter' | 'ghost' | 'filled' | The visual style |
size | 'medium' | 'small' | 'xsmall' | 'xxsmall' | 'medium' | The size of the button |