Skip to content
EspañolEnglish
All components (204)

Button

Actions · Button · .amset-button

What it is and when to use it

The usual button: it does something on the same screen (save, send, delete, open a dialog).

When to use it

  • For an action. If what it does is take you to another page, it is a ButtonLink: it opens in another tab and the screen reader says "link".
  • Only one solid button per screen or per dialog: it is the main action. The rest, outline, soft or ghost.
  • tone="error" for what deletes or cancels an account, better inside a ConfirmAction.
  • startIcon and endIcon to accompany the text; fullWidth to make it take the full width; shape="pill" for rounded corners.

When not to

  • Icon only: IconButton, which forces you to give it a name.
  • Several actions that weigh the same: SplitButton or ActionMenu.

Keyboard: it is a native <button>: Tab reaches it; Enter and Space press it. With disabled it leaves the Tab order. With loading it stays focusable (it carries aria-disabled, not disabled), stops responding to clicks and announces the sending; with loadingText the sending text replaces the content, with no spinner.

Accessibility: the name is the text. Icons are decorative: they never carry information that is not in the text.

Fine-tuning: CSS variables --amset-button-*.

What it looks like

Last change 2 min ago.

<Button variant="solid" tone="accent" startIcon={<SaveIcon />} loading={guardando} loadingLabel="Saving" onPress={guardar}>
  Guardar cambios
</Button>
<Button variant="outline" startIcon={<PlusIcon />}>New order</Button>
<Button variant="outline" endIcon={<DownloadIcon />}>Export</Button>
<Button variant="soft" tone="error" startIcon={<TrashIcon />}>Delete</Button>
<Button variant="ghost">Cancel</Button>
<Button variant="solid" disabled>Unavailable</Button>
<Button variant="solid" size="sm" shape="pill">Small and round</Button>
<ToggleButton label="Favourite" icon={<StarIcon />} defaultSelected variant="outline" />
<TextButton onPress={deshacer}>Undo</TextButton>

Props

Import it with import { Button } from '@amset/ui'. Required props are marked.

PropTypeWhat it does
childrenrequiredReactNode—
classNamestring—
disabledbooleanOut of play: it cannot be pressed, cannot be focused and is not in the tab order.
endIconReactNodeIcon after the text (an arrow, a menu chevron).
excludeFromTabOrderbooleanOut of the tab order but pressable. For a button that duplicates something already in it: the one that opens the list of a search field, which does nothing the down arrow does not.
fullWidthbooleanTakes up the whole available width. On mobile this is usually what you want.
loadingbooleanSubmitting state. The button stays focusable (`aria-disabled`), stops responding to presses and announces the change to the screen reader. It does not change width: the spinner goes over the text, not beside it.
loadingLabelstringWhat is announced while the sending lasts.
loadingTextstringThe text shown INSTEAD of the content while sending: "Saving…". No spinner on top: the text is the notice, and it is announced when it changes. It is what a front end did by swapping its `children` by hand. The button changes width if the new text is a different size.
onClickMouseEventHandler<HTMLButtonElement>—
onPressPressHandler—
shape"default" | "pill"The shape: `default` (the default) or `pill`, with fully rounded corners. Inside a `ButtonGroup` only the outer corners of the group are rounded. For the round icon-only button, `IconButton`.
size"sm" | "md" | "lg"—
startIconReactNodeIcon before the text. Decorative: the text is what counts.
styleCSSPropertiesInline style. The stable look goes in the `--amset-button-*` CSS variables, which is what is maintained; this is for what is only known at run time: a colour chosen by whoever uses the application, a calculated position, a height that depends on the content. It used to be forbidden and had to be opened: a real front end used it on 40 buttons to calculate their halo from an arbitrary colour (AMS-735), and without it the only way out was to write CSS by hand against our classes.
tone"neutral" | "accent" | "secondary" | "tertiary" | "info" | "success" | "warning" | "error"What it means. Without it, a solid or soft button is `accent` (the main action) and an outline or ghost one is `neutral`. `error` is the one for deleting or cancelling an account.
variant"solid" | "soft" | "outline" | "ghost"How it is drawn: `solid`, `soft`, `outline` (default) or `ghost`.

It also accepts the attributes of the element it renders: className, style, data-*, aria-* and its events.

CSS variables

These CSS variables are how you adapt it. Declare them on the component's selector, not on :root: the stylesheet redeclares them in the rule itself, and a declaration on the same element always wins.

VariableDefault
--amset-button-colorvar(--amset-ink)
--amset-button-inkvar(--amset-surface)
--amset-button-softvar(--amset-divider)
--amset-button-textvar(--amset-ink)
--amset-button-text-activevar(--amset-button-text)
--amset-button-bordervar(--amset-border-bold)
--amset-button-heightvar(--amset-height-control)
--amset-button-paddingvar(--amset-space-3)
--amset-button-fontvar(--amset-text-base)
--amset-button-icon1rem
--amset-button-radiusvar(--amset-radius)
--amset-button-weightvar(--amset-weight-bold)
--amset-button-familyvar(--amset-font)
--amset-button-transformnone
--amset-button-spacingnormal
--amset-button-line1
--amset-button-gapvar(--amset-space-2)
--amset-button-shadownone
--amset-button-backgroundtransparent
--amset-button-background-hovervar(--amset-button-background)
--amset-button-background-activevar(--amset-button-background)

How to change it

.amset-button {
  --amset-button-color: ...;
  --amset-button-ink: ...;
}

In the test bench

Every state and variant, to try one at a time, on its page at ui.amset.tech: