Button

Buttons allow users to trigger actions.

The <Button> component is a crucial components of any user interface, allowing users to initiate actions such as submitting forms, adding items to a cart, or opening dialogs. The label on a button indicates the action that will be taken when the user presses it.

Different types of buttons, such as primary and secondary, help guide users by visually prioritizing actions. Primary buttons are typically used for the most important actions, while secondary buttons provide less critical options.

Anatomy

A button consists of a pressable area, often containing a textual label or icon, which users can press or activate using the Space or Enter keys.

Anatomy of a button

Appearance

The appearance of a component can be customized using the variant and size props. These props adjust the visual style and dimensions of the component, available values are based on the active theme.

Variant
Size
PropertyTypeDescription
variantprimary | secondary | destructive | ghost | textThe available variants of this component.
sizedefault | small | large | iconThe available sizes of this component.
About the "secondary" Variant

The core theme does not include a "secondary" button. In the demo above, this variant will default to a regular button without any additional styling.

Usage

Buttons have a wide range of applications. Their most common usage is to submit forms, but they are also used for other actions like opening a <Menu> or <Dialog>.

It is essential that the label and context around the button clearly set expectations for what will happen when the user interacts with it. In user interfaces, buttons guide interactions, providing clear call-to-action elements that help users navigate and complete tasks.

Do

Write button text that is clear, starts with a verb, and helps users confidently take action.

Do
Keep button labels short and to the point.

Visual hierarchy

This primary button should represent the most crucial action within that section. Having multiple primary buttons in one section can create confusion and visual clutter, as they compete for the user's attention and detract from the clarity of the intended action.

Do
Use one primary button per page or section to highlight the most important action

Use one primary button per page or section to highlight the most important action

Don't
Don't include multiple primary buttons in the same section to prevent confusion and visual clutter.

Don't include multiple primary buttons in the same section to prevent confusion and visual clutter.

Icons and labels

Icons can reinforce text labels, but they can also cause confusion if they don't clearly match the related text. Buttons should always have a label unless they use an icon that is universally understood and accessible.

Accompany labels with icons only when they have a strong association with the text, never use icon purely for decoration.

Icon-only buttons should only be used when the icon is universally recognized and its function is clear without additional text, like a pencil for editing. These buttons are particularly useful in compact spaces or mobile interfaces where screen real estate is limited.

Keep it accessible

For icon-only buttons, ensure you set an aria-label or aria-labelledby attribute to provide context and maintain accessibility.

Do
Use icons in buttons to provide additional clarity when the icon is highly relevant to the action.

Use icons in buttons to provide additional clarity when the icon is highly relevant to the action.

Don't
Icons should not be used for decoration.

Icons should not be used for decoration.

Avoid disabled buttons

A disabled button can't be actioned. Keep buttons active and use validation and error messages to guide users on what needs to be done to proceed.

Disabled buttons are problematic as they offer no feedback on why an action is unavailable, are often hard to see due to low contrast, and are inaccessible to keyboard users who cannot focus on them.

Do
Use validation and error messages to guide users on the necessary steps.

Use validation and error messages to guide users on the necessary steps.

Don't
Don't disable form submission buttons, as this doesn't clearly guide users on how to proceed.

Don't disable form submission buttons, as this doesn't clearly guide users on how to proceed.

In general, it's best to avoid using disabled buttons. However, if they are necessary, take steps to make them more inclusive. Ensure users don't get stuck by providing additional information. Place a message near the disabled button that explains why it is unavailable and what actions are needed to enable it.

Only Fanclub members can add a discount code. If you're a Fanclub member, please log in first.

Never put tooltips on disabled buttons

Tooltips aren't accessible on all devices or by some assistive technologies, and they should never be used on non-interactive elements. For more information see the tooltip page.

Loading state

The <Button> component includes a loading property that can be used to display loading behavior. This visually indicates the progress of system operations, such as downloading, uploading, or processing tasks. The loading spinner always shows an indeterminate progress to signify that the duration of the operation is unknown.

This functionality is especially useful when performing actions like submitting a form or saving changes in your application that require time to complete a request. While the button is in the loading state, it becomes disabled, preventing further interaction until the operation is completed.

The button's label should clearly describe the action being performed, providing context for the current state of the process, like also mentioned in Icons and labels.

When the loading state is activated, the label becomes hidden. To ensure accessibility, we provide the loading state with an aria-label and aria-busy.

The loading property must be added manually to a Button, and is intended for processes that typically last more than 1 second.

Full-width

Full-width buttons are especially useful for emphasizing primary actions like submitting a form or completing a purchase, as they attract attention and create a strong visual hierarchy. They also enhance usability on mobile devices or in narrow layouts by providing a larger, easier-to-tap target.

If the user interacts with the element and it results in navigation to another page without submitting a form, use an anchor element (<Link>). For all other interactions that perform actions on the same page, use a button (<Button>).

Understanding this distinction is crucial: anchors handle navigation, while buttons handle page-specific actions. Misusing them can cause accessibility and usability issues, as anchors support tab-opening and navigation, while buttons do not.

To visually imitate a button element that navigates (e.g., a "Cancel" action that redirects users to the previous page), use the <Link> component with the corresponding variant, usually secondary. This way, the action is clear and prominent while keeping its navigation function.

Cancel
Do

Use buttons to trigger an event or an action.

Don't

Don't use buttons for navigation purposes.

Press Event

The <Button> component supports user interactions via mouse, keyboard, and touch, handled through the onPress prop. This prop is similar to the standard onClick event but is normalized for all interaction methods. Additionally, onPressStart, onPressEnd, and onPressChange events are fired during user interaction.

Each handler receives a PressEvent, providing details about the target and the type of event that triggered the interaction, like the pointer (mouse, keyboard or touch) that was used.

Number of times pressed: 0 (Button not pressed.)

Props

Did you know? You can explore, test, and customize props live in Marigold's storybook. Watch the effects they have in real-time!
aria-controls?
string;
Identifies the element (or elements) whose contents or presence are controlled by the current element.
aria-current?
boolean | "true" | "false" | "page" | "step" | "location" | "date" | "time";
Indicates whether this element represents the current item within a container or set of related elements.
aria-describedby?
string;
Identifies the element (or elements) that describes the object.
aria-details?
string;
Identifies the element (or elements) that provide a detailed, extended description for the object.
aria-expanded?
boolean | "true" | "false";
Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed.
aria-haspopup?
boolean | "true" | "false" | "menu" | "listbox" | "tree" | "grid" | "dialog";
Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element.
aria-label?
string;
Defines a string value that labels the current element.
aria-labelledby?
string;
Identifies the element (or elements) that labels the current element.
aria-pressed?
boolean | "true" | "false" | "mixed";
Indicates the current "pressed" state of toggle buttons.
autoFocus?
boolean;
Whether the element should receive focus on render.
children?
ReactNode;
Children of the component
className?
string;
Class of the component.
disabled?
boolean;
Disables the button.
Defaults to:
"false"
excludeFromTabOrder?
boolean;
Whether to exclude the element from the sequential tab order. If true, the element will not be focusable via the keyboard by tabbing. This should be avoided except in rare scenarios where an alternative means of accessing the element or its functionality via the keyboard is available.
form?
string;
The <form> element to associate the button with. The value of this attribute must be the id of a <form> in the same document.
formAction?
string;
The URL that processes the information submitted by the button. Overrides the action attribute of the button's form owner.
formEncType?
string;
Indicates how to encode the form data that is submitted.
formMethod?
string;
Indicates the HTTP method used to submit the form.
formNoValidate?
boolean;
Indicates that the form is not to be validated when it is submitted.
formTarget?
string;
Overrides the target attribute of the button's form owner.
fullWidth?
boolean;
Stretches the button width with full available space.
Defaults to:
"false"
id?
string;
The element's unique identifier. See MDN.
loading?
boolean;
Whether the button is in a loading state. This disables press and hover events while retaining focusability, and announces the loading state to screen readers.
name?
string;
Submitted as a pair with the button's value as part of the form data.
onBlur?
(e: FocusEvent<Element, Element>) => void;
Handler that is called when the element loses focus.
onClick?
(e: MouseEvent<FocusableElement, MouseEvent>) => void;
Not recommended – use onPress instead. onClick is an alias for onPress provided for compatibility with other libraries. onPress provides additional event details for non-mouse interactions.
onFocus?
(e: FocusEvent<Element, Element>) => void;
Handler that is called when the element receives focus.
onFocusChange?
(isFocused: boolean) => void;
Handler that is called when the element's focus status changes.
onHoverChange?
(isHovering: boolean) => void;
Handler that is called when the hover state changes.
onHoverEnd?
(e: HoverEvent) => void;
Handler that is called when a hover interaction ends.
onHoverStart?
(e: HoverEvent) => void;
Handler that is called when a hover interaction starts.
onKeyDown?
(e: KeyboardEvent) => void;
Handler that is called when a key is pressed.
onKeyUp?
(e: KeyboardEvent) => void;
Handler that is called when a key is released.
onPress?
(e: PressEvent) => void;
Handler that is called when the press is released over the target.
onPressChange?
(isPressed: boolean) => void;
Handler that is called when the press state changes.
onPressEnd?
(e: PressEvent) => void;
Handler that is called when a press interaction ends, either over the target or when the pointer leaves the target.
onPressStart?
(e: PressEvent) => void;
Handler that is called when a press interaction starts.
onPressUp?
(e: PressEvent) => void;
Handler that is called when a press is released over the target, regardless of whether it started on the target or not.
preventFocusOnPress?
boolean;
Whether to prevent focus from moving to the button when pressing it. Caution, this can make the button inaccessible and should only be used when alternative keyboard interaction is provided, such as ComboBox's MenuTrigger or a NumberField's increment/decrement control.
ref?
Ref<HTMLButtonElement>;
Allows getting a ref to the component instance. Once the component unmounts, React will set ref.current to null (or call the ref with null if you passed a callback ref). @see {@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
slot?
string | null;
A slot name for the component. Slots allow the component to receive props from a parent component. An explicit null value indicates that the local props completely override all props received from a parent.
type?
"button" | "submit" | "reset";
The behavior of the button when used in an HTML form.
Defaults to:
'button'
value?
string;
The value associated with the button's name when it's submitted with the form data.

Alternative components

  • Link: A component to navigate to another page.
Last update: 6 months ago