Button
Pill-shaped button with gradient emphasis variants, a loading state and asChild support.
Installation
$npx shadcn@latest add @reziui/buttonInstalls the theme tokens too if they are missing. Run npx shadcn@latest add @reziui/theme
first to apply the full Rezi UI palette — see Installation.
Usage
import { Button } from "@/components/ui/button";
export function Example() {
return <Button>Save changes</Button>;
}Examples
Variants
| Variant | Use for |
|---|---|
default | The primary action on a screen. Blue gradient, white label. |
secondary | Most other actions. Surface fill with a 1px ring. |
outline | Actions on tinted or busy backgrounds. Transparent fill. |
ghost | Low-emphasis actions in toolbars and menus. |
destructive | Irreversible actions such as delete. Red gradient. |
destructive-secondary | Less prominent destructive actions. Red label on a surface. |
link | Inline navigation styled as text. |
Sizes
| Size | Height | Notes |
|---|---|---|
xs | 20px | Dense tables and tags. |
sm | 26px | Compact toolbars. |
default | 36px | Standard forms and dialogs. |
lg | 40px | Hero and page-level calls to action. |
icon-xs · icon-sm · icon · icon-lg | 20 · 26 · 36 · 40px | Icon-only, always circular. |
Icon-only buttons have no visible text — always pass aria-label.
Loading
loading disables the button, sets aria-busy and shows a spinner before the label.
With asChild, no spinner is injected (Slot needs exactly one child); only
aria-busy and data-loading are set, so style the loading state yourself.
Success
Pass success (controlled) to cross-fade the label to a check and
successLabel ("Saved" by default) after an async action, then reset it
yourself. The button always hugs what it shows: while loading it shrinks to
an icon-only circle with the spinner, then grows to fit the success label
(200ms; instant under reduced motion). The button keeps its name while loading
and the success label is announced to screen readers.
Keep the button's container from depending on its width (e.g. not centered among siblings that would shift), since it changes size during the morph.
As a link
<Button asChild variant="secondary">
<a href="/pricing">See pricing</a>
</Button>API reference
| Prop | Type | Default |
|---|---|---|
variant | "default" | "secondary" | "outline" | "ghost" | "destructive" | "destructive-secondary" | "link" | "default" |
size | "xs" | "sm" | "default" | "lg" | "icon-xs" | "icon-sm" | "icon" | "icon-lg" | "default" |
loading | boolean | false |
asChild | boolean | false |
static | boolean | false |
success | boolean | — |
successLabel | ReactNode | "Saved" |
All native <button> props are forwarded.
Buttons scale to 96% while pressed; static turns that off where movement would
distract. Both the press scale and the loading spinner stay still under
prefers-reduced-motion — the label and aria-busy still carry the state.