Buttons
Triggers an action. Five variants, plus a semantic range for when the action carries meaning.
Variants
Five fill styles, one per action weight: solid carries the primary action, soft and light tint the surface (soft adapts its tint to dark mode, light stays light in both), outline and ghost recede to chrome. inverted and shadow still render but are legacy - prefer outline.
<div class="flex flex-wrap items-center justify-center gap-3">
<.button>Solid</.button>
<.button variant="soft">Soft</.button>
<.button variant="light">Light</.button>
<.button variant="outline">Outline</.button>
<.button variant="ghost">Ghost</.button>
</div>
Semantic colours
For actions that carry meaning: info, success, warning and danger tint every variant - solid shown here; soften the signal with variant="soft" or "outline". primary, secondary and gray cover everything else.
<div class="flex flex-wrap items-center justify-center gap-3">
<.button color="info">Info</.button>
<.button color="success">Success</.button>
<.button color="warning">Warning</.button>
<.button color="danger">Danger</.button>
</div>
Sizes
Five sizes, xs to xl, md the default. Padding, type and icon scale together, so a size change never needs a class override.
<div class="flex flex-wrap items-center justify-center gap-3">
<.button size="xs">Extra small</.button>
<.button size="sm">Small</.button>
<.button size="md">Medium</.button>
<.button size="lg">Large</.button>
<.button size="xl">Extra large</.button>
</div>
States
icon renders a Heroicon beside the label; icon_placement="right" moves it after, for arrows and continues. loading swaps the icon's side for a spinner so the button never reflows mid-submit, and disabled mutes the button and blocks the click.
<div class="flex flex-wrap items-center justify-center gap-3">
<.button>Default</.button>
<.button icon="hero-rocket-launch">With icon</.button>
<.button icon="hero-arrow-right" icon_placement="right">Continue</.button>
<.button loading>Loading</.button>
<.button disabled>Disabled</.button>
</div>
Icon button
size="icon" renders a square, md-height button for a lone glyph - toolbars, composers, close affordances. A glyph is not a name, so pair it with an aria-label. Every variant and colour applies.
Properties
| Attribute | Type | Default | Description |
|---|---|---|---|
class
|
any |
nil
|
CSS class |
color
|
string |
"primary"
|
button color
one of: "primary", "secondary", "info", "success", "warning", "danger", "gray", "pure_white", "white", "light", "dark"
|
disabled
|
boolean |
false
|
indicates a disabled state |
icon
|
any |
nil
|
name of a Heroicon rendered beside the label |
icon_placement
|
string |
"left"
|
which side of the label the icon sits on - and where the loading spinner appears, so the layout doesn't jump when a button enters its loading state
one of: "left", "right"
|
label
|
string |
nil
|
labels your button |
link_type
|
string |
"button"
|
one of: "a", "live_patch", "live_redirect", "button"
|
loading
|
boolean |
false
|
indicates a loading state |
radius
|
string |
nil
|
button border radius; when unset the --pc-radius theme token applies
one of: nil, "none", "sm", "md", "lg", "xl", "full"
|
rest
|
global |
||
size
|
string |
"md"
|
button sizes; icon renders a square, md-height icon button (pair with an aria-label)
one of: "xs", "sm", "md", "lg", "xl", "icon"
|
to
|
string |
nil
|
link path |
variant
|
string |
"solid"
|
button variant. solid/soft/light/outline/ghost are the supported fill styles (soft adapts its tint to dark mode; light stays light in both modes). inverted and shadow are legacy, slated for removal in a future major - prefer outline, and compose effects (border_beam / shine_border) for flourish
one of: "solid", "soft", "light", "outline", "inverted", "shadow", "ghost"
|
with_icon
|
boolean |
false
|
legacy: icon spacing is part of the base button now; kept for compatibility, removed in 5.0 |
:inner_block
slot
|
slot |
| Attribute | Type | Default | Description |
|---|---|---|---|
class
|
any |
nil
|
CSS class |
color
|
string |
"gray"
|
one of: "primary", "secondary", "info", "success", "warning", "danger", "gray"
|
disabled
|
boolean |
false
|
indicates a disabled state |
link_type
|
string |
"button"
|
one of: "a", "live_patch", "live_redirect", "button"
|
loading
|
boolean |
false
|
indicates a loading state |
radius
|
string |
"full"
|
button radius
one of: "none", "sm", "md", "lg", "xl", "full"
|
rest
|
global |
||
size
|
string |
"sm"
|
one of: "xs", "sm", "md", "lg", "xl"
|
to
|
string |
nil
|
link path |
tooltip
|
string |
nil
|
tooltip text |
with_icon
|
boolean |
false
|
adds some icon base classes |
:inner_block
slot
|
slot |