Manual UI Templates Button

Button

elements man ui/templates/button

A button or a link that looks like one, in six variants and four sizes.

Example
import { Button } from "@elements/ui/button"; import { Icon } from "@elements/ui/icon"; <Button variant="primary" onclick={() => save(form)}>Save changes</Button> <Button variant="ghost" icon label="Close"><Icon name="x" /></Button> <Button href="/docs" variant="link">Read the docs</Button> <Button variant="primary" loading={state.saving}>Save</Button>

Parts

Part What it is
.button The <button> or <a>. Usable without the template: class="button is-primary is-sm".
.button-label Wraps the slot; hidden (not removed) while loading so the width holds.
.button.is-xs / .is-round Extra-small size and fully rounded corners, usable without the template.
.button-spinner The loading ring: a Spinner (.spinner) sized to the button, centered over the label.

Attributes

Attribute Type Default Description
variant "primary" | "secondary" | "outline" | "ghost" | "link" | "danger" "outline" Visual intent. primary is the accent fill, danger is destructive, link is text.
size "xs" | "sm" | "md" | "lg" "md" Height, padding and type size from the theme's control tokens. xs steps down from sm.
icon boolean false Square, icon-only button in any size. Requires label.
round boolean false Fully rounded corners: a pill, or a circle with icon.
label string "" Accessible name (aria-label). Required with icon.
href string "" Renders an <a> instead of a <button>.
type "button" | "submit" | "reset" "button" The button's form behavior. Ignored with href.
disabled boolean false Not interactive. A disabled link loses its href and leaves the tab order.
focusableWhenDisabled boolean false A disabled button stays focusable and in the tab order (aria-disabled), so focus is not lost while it is disabled.
loading boolean false Shows the Spinner ring, sized to the button, over the hidden label; the button never changes size. Sets aria-busy and ignores clicks while staying focusable.
block boolean false Full width of its container.
class string "" Extra classes on the element.
attrs Record<string, string | number | boolean | undefined> {} Any other attributes for the element: id, name, value, form, title, aria-*, data-*.
onclick (e: MouseEvent) => void () => {} Click handler. Not called while disabled or loading.

Slots

Slot Content
default The label: text, an <Icon>, or both. Icons size from --icon-size.

Keyboard

Keys Action
Enter Activates the button or follows the link.
Space Activates a <button>.

Data attributes

Attribute Values On
data-variant the variant root
data-size "xs" | "sm" | "md" | "lg" root
data-loading present while loading root
data-disabled present while disabled root

Accessibility

  • Renders a native <button> (type="button" by default) or <a>, so Enter, Space and form submission work without script.
  • An icon-only button gets its name from label; the template warns in the console when it is missing.
  • Loading sets aria-busy="true" and aria-disabled="true" but keeps focus on the button, so a keyboard user is not dropped to the top of the page mid-save.
  • A disabled link gets aria-disabled="true", role="link", no href and tabindex="-1".
  • focusableWhenDisabled keeps a disabled button focusable with aria-disabled="true"; clicks and keys do nothing.
  • aria-labelledby and aria-describedby pass through attrs.
  • aria-invalid="true" through attrs draws a danger border, and a danger focus ring, for a button that stands for a field with an error.
  • A button that opens a dialog ends its label with an ellipsis ("Rename…"), as the APG asks.

See also