Button
Buttons start an action, like saving a form or opening a dialog.
A button starts an action: something happens when you select it, like saving a form, opening a dialog, or deleting an item. Its appearance tells how important the action is, and its color tells what kind of action it is.
Use a button for:
- An action that changes something, like Save, Delete, or Enable
- Confirming or dismissing a dialog
- Opening a dialog or a menu
Don't use a button for:
- Going somewhere else. Use a link instead.
- An action that takes a while and needs to show how it went. Use a progress button.
- A list of actions. Put them in a dropdown.
- Turning a setting on or off. Use a switch.
- Container: the background, border, and corner radius
- Start: optional content before the label, usually an icon
- Label: the text of the button
- End: optional content after the label, usually an icon
- Spinner: replaces the start, label, and end while the button is loading
A button has four appearances. They set how much attention it draws:
- Accent is the default, with the loudest fill.
- Filled has a softer fill. Use it when an action needs emphasis.
- Outlined has no fill, only a border.
- Plain has no fill and no border, and draws the least attention. Use it for cancel and dismiss actions.
The variant sets the color, and with it the meaning:
- Brand is the default, for most actions.
- Danger is for destructive actions, like deleting something.
- Warning and success are for actions that relate to a warning or a success state.
- Neutral is for actions that should not carry any meaning through color.
Buttons come in four sizes: extra small, small, medium, and large. Medium is the default.
- Enabled: the resting state, with the colors of its appearance and variant.
- Hover: on devices with a pointer that can hover, the background changes to the hover fill of the variant. The color change takes 150 ms.
- Focus: keyboard focus shows a 2px solid focus ring, 2px outside the button.
- Pressed: while pressed, the background changes to the active fill of the variant.
- Disabled: the button uses the disabled colors, can't be selected, and is skipped when you move through the page with the keyboard.
- Loading: a spinner replaces the label and icons. The button keeps its size, and selecting it does nothing.
Long labels wrap to a new line. When a label can't wrap, it is cut off with an ellipsis.
| Size | Height | Padding left and right | Font size |
|---|---|---|---|
| Extra small | 24px | 8px (--ha-space-2) |
14px (--ha-font-size-m) |
| Small | 32px | 12px (--ha-space-3) |
14px (--ha-font-size-m) |
| Medium | 40px | 16px (--ha-space-4) |
14px (--ha-font-size-m) |
| Large | 48px | 16px (--ha-space-4) |
16px (--ha-font-size-l) |
The height can be changed with --ha-button-height. In code there is also an extra large size, but it has no style of its own and looks the same as medium.
| Property | Value | Token |
|---|---|---|
| Corner radius | 9999px, fully rounded | --ha-border-radius-pill, through --ha-button-border-radius |
| Border width | 1px | --ha-border-width-sm |
| Font weight | 500 | --ha-font-weight-medium |
| Padding next to a start or end icon | 8px | --ha-space-2 |
| Gap between icon and label | 4px | --ha-space-1 |
| Label padding top and bottom | 4px | --ha-space-1 |
| Icon size in extra small | 16px | --mdc-icon-size |
| Focus ring | 2px solid, 2px offset | --ha-color-focus |
| Hover transition | 150ms, ease-out | --ha-animation-duration-fast |
The tokens below are for the brand variant. The other variants use the same tokens with neutral, success, warning, or danger in place of primary.
| Appearance | State | Background | Text | Border |
|---|---|---|---|---|
| Accent | Resting | --ha-color-fill-primary-loud-resting |
--ha-color-on-primary-loud |
Transparent |
| Accent | Hover | --ha-color-fill-primary-loud-hover |
--ha-color-on-primary-loud |
Transparent |
| Accent | Pressed | --ha-color-fill-primary-loud-active |
--ha-color-on-primary-loud |
Transparent |
| Accent | Disabled | --ha-color-fill-disabled-loud-resting |
--ha-color-on-disabled-loud |
Transparent |
| Filled | Resting | --ha-color-fill-primary-normal-resting |
--ha-color-on-primary-normal |
Transparent |
| Filled | Hover | --ha-color-fill-primary-normal-hover |
--ha-color-on-primary-normal |
Transparent |
| Filled | Pressed | --ha-color-fill-primary-normal-active |
--ha-color-on-primary-normal |
Transparent |
| Filled | Disabled | --ha-color-fill-disabled-normal-resting |
--ha-color-on-disabled-normal |
Transparent |
| Outlined | Resting | Transparent | --ha-color-on-primary-quiet |
--ha-color-border-primary-loud |
| Outlined | Hover | --ha-color-fill-primary-quiet-hover |
--ha-color-on-primary-quiet |
--ha-color-border-primary-loud |
| Outlined | Disabled | Transparent | --ha-color-on-disabled-quiet |
--ha-color-on-disabled-quiet |
| Plain | Resting | Transparent | --ha-color-on-primary-normal |
Transparent |
| Plain | Hover | --ha-color-fill-primary-quiet-hover |
--ha-color-on-primary-normal |
Transparent |
| Plain | Pressed | --ha-color-fill-primary-quiet-active |
--ha-color-on-primary-quiet |
Transparent |
| Plain | Disabled | Transparent | --ha-color-on-disabled-quiet |
Transparent |
The neutral plain button is the one exception: pressed, it uses --ha-color-fill-neutral-normal-active. A disabled button made disabled through its attribute is also dimmed to 50% opacity as a whole, by the Web Awesome base style.
See UI text and remove, delete, add, or create for more.
Avoid icons in extra small buttons. At 24px the label carries the meaning on its own, and a 16px icon next to it adds noise without adding information. Use an icon only when the button needs to be recognized at a glance in a dense layout, and only a common one that people recognize by its shape alone, like close, add, or settings.
| Key | Action |
|---|---|
| Tab | Moves focus to the button, and away from it. A disabled button is skipped. |
| Enter or Space | Selects the button. Does nothing while it is loading. |
The focus ring only shows for keyboard focus, not when you select the button with a mouse or touch.
The height is 24px for extra small, 32px for small, 40px for medium, and 48px for large. The width follows the label, plus the padding.
A screen reader announces a button with its label. A button with only an icon has no text to announce, so it needs a name in code. While it loads, the button is announced as busy. A disabled button is announced as disabled.
- Focus is delegated to the native
<button>inside the component, so callingfocus()on<ha-button>focuses the button. The focus ring uses:focus-visible. - The role is
button. The accessible name is the label text. Setaria-labelon<ha-button>to give it another name: it is passed on to the native button. - A button with only an icon and no text needs an
aria-label. - While loading, the button has
aria-busy="true". - A disabled button is a native disabled
<button>.
- Progress button: a button that shows the result of its action
- Dropdown: a button that opens a menu of actions
- Dialog: where most button pairs live
- UI text: how to write labels
The element is <ha-button>. It is based on the Web Awesome button.
<ha-button>Save</ha-button>
<ha-button appearance="plain">Cancel</ha-button>
<ha-button variant="danger">Delete</ha-button>
<ha-button size="s">Small</ha-button>In a dialog, put the main action in the primaryAction slot and the secondary action in the secondaryAction slot of ha-dialog-footer.
appearance:accent(default),filled,outlined, orplain.variant:brand(default),neutral,success,warning, ordanger.size:xs,s,m(default), orl. The valuexlis accepted as well, and looks the same asm.loading: shows a loading indicator instead of the label, and blocks selecting the button.disabled: disables the button.
- Default: the label.
start: content before the label, usually an icon.end: content after the label, usually an icon.
--ha-button-height: the height of the button.--ha-button-border-radius: the corner radius. Defaults tovar(--ha-border-radius-pill).
Source: src/components/ha-button.ts