API and Development
Button is used to take action by clicking or pressing a specific key.
| Name | Type | Default | Description |
|---|---|---|---|
active | boolean | — | Non-toggle pressed or transient current marker; hosts write the pressed state key through stateAttributes (data-pressed).
A toggle host (Button toggle variant) uses aria-pressed and styles with [aria-pressed="true"] without also writing data-pressed for that toggle state (ADR 0001 rule 1).
Link "current" within a set uses aria-current, not active.
active paints data-pressed and conflicts with toggle aria-pressed; not on toggle buttons. |
aria-controls | string | — | Id of the element controlled by this control. |
aria-current | boolean | "time" | "false" | "true" | "page" | "step" | "location" | "date" | — | Whether this item is current within a set. |
aria-describedby | string | — | Id of the element that describes this control. |
aria-description | LocalizedMessage | — | Accessible description when it cannot be referenced by id. |
aria-expanded | boolean | — | Whether the controlled region is expanded. |
aria-haspopup | boolean | "dialog" | "menu" | "false" | "true" | "listbox" | "tree" | "grid" | — | Type of popup triggered by this control, if any. |
aria-label | LocalizedMessage | — | Accessible name when the visible label is insufficient. |
aria-labelledby | string | — | Id of the element that names this control. |
children | ReactNode | — | Visible label. Visible label; omit for icon-only. |
className | string | — | @deprecated Pass layout through enum props and shipped parts. Request a missing case via find-pattern. |
defaultPressed | boolean | — | Initial on state when uncontrolled. |
disabled | boolean | — | Inert state per host: native disabled on a button; on Link, ADR 0006 link host (no href, aria-disabled="true", tabIndex={0}).
Never tabIndex={-1}. |
fullSpan | boolean | false | When true, the control fills the available inline size of its parent (inline-size: 100%). Only the inline axis fills; block size stays at the control token in every host.
Icon-only controls always hug; fill is not available. |
icon | ReactNode | — | Icon-only glyph; use with {@link ButtonIconOnlyProps} instead. Icon slot, usually {@link Icon }. |
id | string | — | Element id for ARIA relationships. |
intent | ButtonIntent | — | Visual intent. Defaults to {@link ButtonIntent.Neutral}. |
label | LocalizedMessage | DisplayValue | — | Icon-only accessible name; use with {@link ButtonIconOnlyProps} instead. Accessible name rendered through {@link VisuallyHidden }. |
leading | ReactNode | — | Content before the label. |
loading | boolean | — | Composed loading state: disables the control, sets aria-busy, and shows a spinning loader glyph before the label.
Loading is not defined for toggle buttons. |
loadingLabel | LocalizedMessage | — | Accessible name while loading; rendered through {@link VisuallyHidden }. Loading label is not defined for toggle buttons. |
onPressedChange | ((pressed: boolean, details: ChangeDetails<ChangeReason>) => void) | — | Called when the toggle changes from a click or Enter/Space activation. @param pressed - Next pressed state @param details - Change metadata; cancel to keep the previous state |
pressed | boolean | — | Whether the toggle is on (controlled). |
pressedIcon | ReactNode | — | The pressed icon belongs to an icon-only toggle; see {@link ButtonToggleProps.pressedIcon}.
Icon shown in place of icon while the toggle is on, for an icon-only toggle whose glyph shows the state (an
outlined star that fills, a bell that gains a slash). The accessible name stays label in both states, and
aria-pressed carries the state, so the glyph is never the only signal. Without it icon shows in both states.
Not defined with children: a labelled button keeps one label and its leading and trailing slots. |
preventFocusOnPress | boolean | false | When true, mousedown does not move focus to the button (field adornments). |
ref | Ref<HTMLButtonElement> | — | Ref to the rendered button. |
shape | ButtonShape | — | Corner shape. Defaults to {@link ButtonShape.Control}. |
size | ButtonSize | — | Control size. Defaults to {@link ButtonSize.Large}. |
softFill | ButtonSoftFill | ButtonSoftFill.Outline | Fill for {@link ButtonVariant.Soft}. {@link ButtonSoftFill.Outline} is the default secondary (Neutral, bordered, transparent). {@link ButtonSoftFill.Filled} keeps the tinted Neutral Soft fill for segmented selections and other cases that need a filled surface. |
tooltip | LocalizedMessage | DisplayValue | — | Short text shown in a Tooltip while the pointer hovers the button or a navigation key focuses it. Button
composes Tooltip's trigger, content and root, so it behaves like Tooltip > TooltipTrigger > Button and also works
while disabled (pointer only) and on toggle buttons. A labelled button points aria-describedby at the tooltip.
An icon-only button does not: label already names it, so the tooltip is visual only and never read twice.
Adding or removing the prop after mount remounts the button. |
trailing | ReactNode | — | Content after the label. |
type | "button" | "submit" | "reset" | — | Native button type. Defaults to button. |
variant | ButtonVariant | — | Surface variant. Defaults to {@link ButtonVariant.Soft}. |
packages/ui/src/components/button/button.figma.ts; once it is published, Dev Mode shows <Button intent={ButtonIntent.Accent} ...> with real enum members. See Figma Code Connect.
Use to designate key actions, such as accepting a condition that changes the product state. Allow one critical button per page; don't use alongside a primary button.
<Button> or SECONDARY_BUTTON_LAYOUT renders neutral soft outline by default. Set softFill={ButtonSoftFill.Filled} only when a filled neutral soft surface is required.
Link from @prepared911/ui/link, not Button. Button has no href. Use variant={ButtonVariant.Plain} when the control is an action that should look like text. Use Link with appearance={LinkAppearance.Button} when a destination should look like a button.
Internal links open in the same browser tab.
external and newTabLabel. The link opens in a new tab and the label names that behavior.
size={ButtonSize.Coarse} with intent={ButtonIntent.Success} and variant={ButtonVariant.Solid} in an equal-width row (Grid with template={GridTemplate.EqualHalves} and fullSpan on each button). Type, icon, gap, and radius scale with this size.
Use frequently for most actions. This is the default when size is omitted.
Use when you need a slightly shorter control than large without going to the compact size.
Use in tight spaces, such as sidebars and floating elements; only pair with other small-sized buttons.
Use to identify or differentiate the button's usage, such as a "+" icon when adding something.
active marks a momentary or current control with data-pressed and does not set aria-pressed. Use pressed and onPressedChange when the control must stay pressed.
pressed or defaultPressed with onPressedChange. The button sets aria-pressed. There is no toggle prop and no separate toggle type. Do not change the visible name when the pressed state changes. Icon-only toggles use icon, label, and pressedIcon when the glyph changes.
Do not use these props inside a ToggleGroup. Group items remain ToggleGroupItem.
loading keeps the label visible, sets aria-busy, and disables the button. loadingLabel is the accessible name of the busy state. There is no loading-type enum.