Button
PreviewA native button with a loading state and a disabled state that can keep focus.
Features
Permalink to heading "Features"- Renders a native
<button>and setstype="button"by default, so a button inside a form never submits it by accident - passtype="submit"for the submit button disabledandloadingstates, a loading button is disabled toofocusableWhenDisabledkeeps a disabled button in the tab order, so focus is not lost when it gets disabledindicatorparts show and hide content per state, for loading spinners and text changes- Works as the
asChildtarget of triggers likeui:collapsible.triggerand as the building block of your own components
Unlike most components the button has no root part. It is a single element with optional parts, so the folder-named file is its root (<ui:button>), see Root or the Folder Name.
<primitives:button>
<primitives:button.indicator state="idle" />
<primitives:button.indicator state="loading" />
<primitives:button.indicator state="disabled" />
</primitives:button>
Installation
Permalink to heading "Installation"typo3 ui:add button
Please copy the files manually from GitHub into your project.
Read more about installing Components and Primitives.
Examples
Permalink to heading "Examples"Disabled
Permalink to heading "Disabled"A disabled button gets the native disabled attribute. Browsers take it out of the tab order, and a focused button loses focus the moment it is disabled.
Focusable When Disabled
Permalink to heading "Focusable When Disabled"With focusableWhenDisabled the button gets aria-disabled="true" instead of the disabled attribute and stays focusable. Clicks and the Enter and Space keys are ignored in the capture phase, before any other listener of the button runs, so it still never submits a form or opens the dialog it triggers. Press Tab to compare the two buttons below.
Loading States
Permalink to heading "Loading States"For a button that starts loading after it was activated, set focusableWhenDisabled so focus stays on it while it is disabled.
Some browser and screen reader combinations do not reliably announce a change of the text inside a focused button. Make the changing text the explicit accessible name instead: wrap the indicators in an element with an id and point aria-labelledby at it.
Each indicator is only visible in its state: idle, loading or disabled. loading wins over disabled, and a state without an indicator renders nothing, so add one for every state the button can be in. Decorative content like a spinner needs aria-hidden="true".
The server renders the state, and on the client you change it with api.setLoading() and api.setDisabled(). Mount the button yourself with autoMount="{false}" and a rootId, as below. ui:button only loads its own auto-mounting entry file for a button with focusableWhenDisabled, because a plain button needs no JavaScript:
For a submit button of a form, pass form.api.isSubmitting as loading, see Forms.
As a Trigger
Permalink to heading "As a Trigger"The button renders a plain <button> and does not set data-state or an id, so a trigger can merge its own attributes onto it with asChild: aria-expanded and data-state come from the collapsible, type and the disabled handling from the button.
The button keeps its own behavior and gets the attributes of the trigger on top.
Custom Components
Permalink to heading "Custom Components"The button is meant to be a part of larger components of your own. Put it into the template, give it a rootId derived from your component's, and mount it from your component's entry file. The component then drives the button from its own logic, here a backup that runs for a moment.
Backup
Last backup 2 days ago
API Reference
Permalink to heading "API Reference"The following tables cover the available props of the Fluid Primitives.
The button. Renders a <button> element.
| Name | Description | Required | Default |
|---|---|---|---|
type | stringThe `type` of the button. It defaults to `button`, so a button inside a form does not submit it. Use `submit` or `reset` to opt in. | No | 'button' |
disabled | booleanWhether the button is disabled. | No | false |
loading | booleanWhether the button is loading. A loading button is disabled too. | No | false |
focusableWhenDisabled | booleanKeeps a disabled button focusable. It then gets `aria-disabled` instead of the `disabled` attribute, and clicks and key presses are ignored. | No | false |
attributes | arrayAdditional attributes that should be rendered on the component where ui:attributes is used. | No | [] |
asChild | booleanIf true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. | No | - |
rootId | stringThe root ID of the component, used for hydration and identification. | No | - |
ids | arrayThe IDs of of the component parts for composition. | No | [] |
autoMount | booleanWhether the client initializes the component on its own. Set it to false to mount it yourself with `mount()` | No | true |
class | stringThe CSS class(es) to be applied to the component. | No | - |
Rendered data attributes
| Attribute | Description |
|---|---|
data-disabled | Present when disabled |
data-loading | Present while the button is loading. |
button.indicator
Permalink to heading "button.indicator"Shows its content only while the button is in its state. Renders a <span> element.
| Name | Description | Required | Default |
|---|---|---|---|
state | Enum\ButtonIndicatorStateThe state of the button this indicator is shown in. | Yes | - |
attributes | arrayAdditional attributes that should be rendered on the component where ui:attributes is used. | No | [] |
asChild | booleanIf true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. | No | - |
class | stringThe CSS class(es) to be applied to the component. | No | - |
Machine options
Permalink to heading "Machine options"| Name | Description | Default |
|---|---|---|
id | stringThe unique identifier of the button. | - |
ids | Record<string, string> | undefinedThe ids of the parts other elements reference: root. | - |
disabled | boolean | undefinedWhether the button is disabled. | - |
loading | boolean | undefinedWhether the button is loading. A loading button is disabled too. | - |
focusableWhenDisabled | boolean | undefinedKeeps a disabled button focusable. It then gets aria-disabled instead of the disabled attribute, and clicks and key presses are ignored. | - |
Machine JavaScript API
Permalink to heading "Machine JavaScript API"| Name | Type | Description |
|---|---|---|
state | ButtonState | The state of the button, which decides the indicators that are shown. |
disabled | boolean | Whether the button is disabled, either on its own or because it is loading. |
loading | boolean | Whether the button is loading. |
setDisabled | (value: boolean) => void | Disables or enables the button. A loading button stays disabled. |
setLoading | (value: boolean) => void | Starts or stops loading. A loading button is disabled too. |
addEventListener | (...args: Parameters<HTMLButtonElement['addEventListener']>) => void | Adds an event listener to the button element, the same as addEventListener of the element. |