Button playground

All variants, sizes, states, and common compositions. Use the controls to switch theme and surface background.

Variants × text sizes

Every variant rendered at sm and md.

primary
secondary
secondary-neutral
outline
outline-neutral
outline-black
info
ghost
ghost-neutral
link
link-secondary
destructive
destructive-ghost

Icon-only sizes

icon-xss, icon-sm, icon-md, icon-lg across each variant.

primary
secondary
secondary-neutral
outline
outline-neutral
outline-black
info
ghost
ghost-neutral
link
link-secondary
destructive
destructive-ghost

States

Disabled and loading per variant.

primary
secondary
secondary-neutral
outline
outline-neutral
outline-black
info
ghost
ghost-neutral
link
link-secondary
destructive
destructive-ghost

In a form

Buttons next to inputs — vertical alignment and height matching.

In a card

Realistic compositions.

Plan upgrade
Move to Pro to unlock advanced analytics and unlimited seats.
Your current plan is Starter.
API key
Used for server-to-server auth.
Danger zone
Irreversible actions.

Toolbar / button group

Mixed icon-only and labeled buttons in a row.

In a dialog

Open the dialog to see footer alignment.

Real-world unusual usages

Patterns found in the codebase that override the variant's intrinsic sizing — verify the inset border still looks right.

Height overrides — h-6 / h-8 / h-10 on top of size
Custom-sized icon buttons — h-6 w-6 with size=icon-sm
h-auto p-0 — content-sized button (ContextVariables refresh)
Multiline / wrapping label — h-auto whitespace-normal (WhatsAppFlow)
asChild — anchor / span as the rendered element
hi@example.comasChild span with h-10 py-4Primary as link
Full-width with justify-between — dropdown trigger pattern
Grid with self-stretch — modal step picker
buttonVariants applied to non-Button (AlertDialog primitives pattern)
Plain anchor (reference)Hand-rolled span with primary classes
isLoading transition — click to toggle
Tight button group — buttons sitting flush against each other
The primary in the middle is where the inset shadow's seam vs neighbours is most visible.

Custom widths

Verify the inset border, gradient fill, and label centering hold at any width.

Fixed pixel widths (md)
Fixed pixel widths (sm)
Tailwind width scale — primary
Same width across variants (w-48)
Long label — confirms text doesn't push the inset border
Constrained container — flex-1 / flex-grow
Full-width — w-full per variant
Icon-only — fixed pixel widths (icon-md)
Icon-only — Tailwind width scale (icon-sm / icon-md / icon-lg)
Icon-only — same width across variants (w-32, icon-md)
Icon-only — full-width / flex-1