Skip to main content

Button

<zeno-button>ActionsForm controlSource

A button, or a link that looks like one when href is set. Inside a form, type="submit" and type="reset" act on that form.

import '@usezeno/tokens/css';
import '@usezeno/core/web-components';

Examples​

Variants​

Primary Secondary Accent Outline Ghost Destructive
<zeno-button variant="primary">Primary</zeno-button>
<zeno-button variant="secondary">Secondary</zeno-button>
<zeno-button variant="accent">Accent</zeno-button>
<zeno-button variant="outline">Outline</zeno-button>
<zeno-button variant="ghost">Ghost</zeno-button>
<zeno-button variant="destructive">Destructive</zeno-button>

Sizes​

Extra small Small Medium Large Extra large
<zeno-button size="xs">Extra small</zeno-button>
<zeno-button size="sm">Small</zeno-button>
<zeno-button size="md">Medium</zeno-button>
<zeno-button size="lg">Large</zeno-button>
<zeno-button size="xl">Extra large</zeno-button>

Disabled and loading​

A loading button keeps its width, shows a spinner and cannot be pressed.

Disabled Saving
<zeno-button disabled>Disabled</zeno-button>
<zeno-button loading>Saving</zeno-button>

With href the element renders a link that looks the same.

Go to this heading
<zeno-button href="#as-a-link" variant="outline">Go to this heading</zeno-button>

In a form​

A submit button runs the form’s validation and adds its own name and value to the data. A reset button puts every control back.

Join Clear

Nothing submitted yet.

<form>
<zeno-input name="email" type="email" label="Email" required></zeno-input>
<zeno-button type="submit" name="action" value="join">Join</zeno-button>
<zeno-button type="reset" variant="ghost">Clear</zeno-button>
<p data-result>Nothing submitted yet.</p>
</form>
const form = document.querySelector('form');
form.addEventListener('submit', event => {
event.preventDefault();
const sent = [...new FormData(form)].map(([name, value]) => name + '=' + value);
document.querySelector('[data-result]').textContent = 'Submitted: ' + sent.join('&');
});

Attributes and properties​

PropertyAttributeTypeDefaultDescription
variantvariantreflectsButtonVariant'primary'
sizesizereflects'sm' | 'md' | 'lg' | 'xl''md'
typetypereflects'button' | 'submit' | 'reset''button'
disableddisabledreflectsbooleanfalse
namenamereflectsstringWith value, the entry a submit button adds to the form it submits.
valuevaluestring
loadingloadingreflectsbooleanfalse
fullWidthfull-widthreflectsbooleanfalse
iconOnlyicon-onlyreflectsbooleanfalse
hrefhrefstring
targettargetstring
relrelstring
downloaddownloadstring
formread onlyHTMLFormElement | nullThe form the button belongs to, if any.
isDisabledread onlybooleanTrue when the element or an ancestor fieldset disables it.
testIdstringTest ID for automated testing From ZenoElement.

Methods​

MethodDescription
focus(): voidFocus the component or its first focusable element From ZenoElement.
blur(): voidBlur the component or its focused element From ZenoElement.

Events​

This element sends no events.

Slots​

SlotDescription
DefaultThe label.
prefixAn icon before the label.
suffixAn icon after the label.

CSS parts​

Part
base
prefix
suffix

CSS custom properties​

This element documents no custom properties of its own. Style it through its parts and through the tokens it reads.

The element's own source reads no tokens.

Types​

type ButtonVariant =
| 'primary' // High-emphasis primary actions
| 'secondary' // Medium-emphasis secondary actions
| 'tertiary' // Low-emphasis actions
| 'outline' // Outlined variant (alias for secondary)
| 'accent' // Accent actions
| 'destructive' // Destructive actions (delete, remove)
| 'ghost' // Minimal emphasis
| 'link' // Text-like actions
| 'glass';

Accessibility​

Keyboard​

KeyWhat it does
TabMoves focus to the button.
EnterSpaceActivates the button. On a submit or reset button this acts on the form.
EnterFollows the link when href is set.

Forms​

This element is form-associated. See its properties above for what it does in a form.

Notes​

  • Renders a native <button> in its shadow root, or a native <a> when href is set, so the role and keyboard behaviour are the browser’s own.
  • Focus is delegated to the inner control. aria-label and the other ARIA attributes set on the element are copied to it.
  • loading disables the inner button and sets aria-busy="true". The spinner is hidden from assistive technology.
  • A disabled link gets aria-disabled="true" and leaves the tab order.
  • An icon-only button has no text, so give it an aria-label.

Tests and known gaps​

  • Tested in a real browser by button.test.ts.
  • Checked with axe-core in the light and the dark theme.
  • Has a Storybook story.
15 of the 24 properties, methods, events, slots and parts above have no description in the source
  • the property variant
  • the property size
  • the property type
  • the property disabled
  • the property value
  • the property loading
  • the property fullWidth
  • the property iconOnly
  • the property href
  • the property target
  • the property rel
  • the property download
  • the part base
  • the part prefix
  • the part suffix

Known gaps:

  • The variant type also lists tertiary, link and glass. The element has no styles for them, so they render as an unstyled button.
  • The xs size is styled, but the size type does not list it, so TypeScript and the framework wrappers reject it.
  • Nothing announces the change when loading starts or ends, beyond aria-busy.
  • An icon-only button without an aria-label has no accessible name, and the element does not warn about it.