Skip to main content

Button

The Button element is an interactive element activated by a user with a mouse, keyboard, finger, voice command, or other assistive technology. Once activated, it then performs an action, such as submitting a form or opening a dialog.

Definition from the MDN web docs

Text

The text property sets the label displayed in the button:

Loading...
Live Editor
<qds-button text="Do something"></qds-button>

Writing guidelines

Make sure to review the Writing for user interfaces general guidelines.

  • Buttons should use action verbs in the active imperative form.
  • Avoid ambiguous actions like "learn more", "see more".
  • Be contextual and use precise verbs that best describe what will happen when the user clicks on the button.
  • In applications, append an ellipsis to the label when clicking the button will open a dialog.

Example

Loading...
Live Editor
<div class="qds-controls qds-related flex-row">
  <qds-button importance="emphasized" text="Save and exit"></qds-button>
  <qds-button text="Don't save"></qds-button>
  <qds-button text="Cancel"></qds-button>
</div>

Icon

Use the icon-name property to display an icon on the button. Quartz will look into the default icon library unless you specify another library using the icon-library property.

In Figma, enable the 🅵 icon toggle to see the icon-name property. See the Usage > Icons instructions for more details.

Loading...
Live Editor
<qds-button icon-name="alarm-clock" text="Set alarm"></qds-button>

Icon-only

Setting an icon-name without text will make the button show only an icon.

In Figma, enable the 🅵 icon toggle and disable the 🅵 text toggle.

Loading...
Live Editor
<qds-button icon-name="alarm-clock"></qds-button>

Icon-only buttons should be used only in specific contexts:

  • to disclose advanced options/settings in a menu. Use subdued importance to make the button less prominent:

    Loading...
    Live Editor
    <qds-button importance="subdued" icon-name="alarm-clock"></qds-button>
    

    TODO: better example + replace with "kebab menu" icon + add the sub-menu.

  • to create toolbars in technical applications:

    Loading...
    Live Editor
    <div class="qds-controls flex-row">
      <div class="qds-controls qds-related flex-row">
        <qds-button icon-name="alarm-clock"></qds-button>
        <qds-button icon-name="alarm-clock"></qds-button>
      </div>
      <div class="qds-controls qds-related flex-row">
        <qds-button icon-name="alarm-clock"></qds-button>
        <qds-button icon-name="alarm-clock"></qds-button>
        <qds-button icon-name="alarm-clock"></qds-button>
        <qds-button icon-name="alarm-clock"></qds-button>
      </div>
      <div class="qds-controls qds-related flex-row">
        <qds-button icon-name="alarm-clock"></qds-button>
        <qds-button icon-name="alarm-clock"></qds-button>
        <qds-button icon-name="alarm-clock"></qds-button>
      </div>
    </div>
    

    TODO: use various icons when available.

Icon guidelines

  • Prefer text buttons by default. Add an icon on the few most important buttons only.
  • Don't put icons on every button.
  • Don't use emphasized importance with an icon-only button.

Importance

Buttons follow the transversal Importance principle through its importance property:

Loading...
Live Editor
<div class="qds-controls qds-related flex-row">
  <qds-button text="Standard"></qds-button>
  <qds-button importance="emphasized" text="Emphasized"></qds-button>
  <qds-button importance="subdued" text="Subdued"></qds-button>
</div>

Standard

Use the standard importance level for almost every button:

Loading...
Live Editor
<div class="qds-controls qds-related flex-row">
  <qds-button text="Action 1"></qds-button>
  <qds-button text="Action 2"></qds-button>
  <qds-button text="Action 3"></qds-button>
</div>

Emphasized

Emphasize only one button on the screen or within a dialog:

Loading...
Live Editor
<div class="qds-controls qds-related flex-row">
  <qds-button importance="emphasized" text="Save and exit"></qds-button>
  <qds-button text="Don't save"></qds-button>
  <qds-button text="Cancel"></qds-button>
</div>

Subdued

Use the subdued importance level for less important or less commonly used actions.

Loading...
Live Editor
<div class="qds-controls flex-row justify-between">
  <qds-button importance="subdued" text="Edit save preferences"></qds-button>
  <div class="qds-controls qds-related flex flex-row">
    <qds-button importance="emphasized" text="Save"></qds-button>
    <qds-button text="Cancel"></qds-button>
  </div>
</div>

Size

Buttons follow the transversal control size principles. Use the standard size unless you're in one of the specific contexts described on that page.

Loading...
Live Editor
<div class="qds-controls qds-related">
  <div class="qds-controls qds-related flex flex-row">
    <qds-label inline text="Standard size:"></qds-label>
    <qds-button importance="emphasized" text="Save"></qds-button>
    <qds-button text="Cancel"></qds-button>
  </div>
  <div class="qds-controls-large qds-related flex flex-row">
    <qds-label inline size="large" text="Large size:"></qds-label>
    <qds-button size="large" importance="emphasized" text="Save"></qds-button>
    <qds-button size="large" text="Cancel"></qds-button>
  </div>
  <div class="qds-controls-small qds-related flex flex-row">
    <qds-label inline size="small" text="Small size:"></qds-label>
    <qds-button size="small" importance="emphasized" text="Save"></qds-button>
    <qds-button size="small" text="Cancel"></qds-button>
  </div>
</div>

Variant

Buttons have edge cases that can be set through the variant property. Don't use it unless you're in one of the specific contexts described here.

Hero

Use the hero variant only on websites.

Loading...
Live Editor
<div class="qds-controls qds-related flex-row">
  <qds-button href="https://example.com/" variant="hero" text="Investor Relations"></qds-button>
  <qds-button href="https://example.com/" importance="emphasized" variant="hero" text="Our Purpose"></qds-button>
  <qds-button href="https://example.com/" importance="subdued" variant="hero" text="More"></qds-button>
</div>

Destructive

Use the destructive variant only for destructive actions that can't be undone.

Loading...
Live Editor
<div class="qds-controls qds-related flex-row">
  <qds-button variant="destructive" text="Delete"></qds-button>
  <qds-button text="Cancel"></qds-button>
</div>

Action

Buttons can display icons depending on their action.

Next

The next action indicates that this button will navigate to a different page. An example of a UI where this can be used is a wizard.

Loading...
Live Editor
<qds-button href="https://example.com/" action="next" text="Next"></qds-button>

The dropdown action indicates that this button opens a dropdown menu.

Loading...
Live Editor
<div class="qds-controls qds-related flex-col">
  <qds-button id="simple-multi-select" text="Select" action="dropdown"></qds-button>
  <qds-dropdown target="#simple-multi-select">
    <div class="flex flex-col">
      <qds-list-item list-action="multiselect" divider="hide" text="This is option 1"></qds-list-item>
      <qds-list-item list-action="multiselect" divider="hide" text="This is option 2"></qds-list-item>
    </div>
  </qds-dropdown>
  <qds-button text="Button 2"></qds-button>
  <qds-button text="Button 3"></qds-button>
</div>

Layout

Order

Per the Norman/Nielsen recommendation, follow the Windows platform convention and put the default/emphasized button first:

Loading...
Live Editor
<div class="qds-controls qds-related flex-row">
  <qds-button importance="emphasized" text="Save"></qds-button>
  <qds-button text="Cancel"></qds-button>
</div>

Grouping

Follow the transversal controls spacing guidelines when working with buttons:

Loading...
Live Editor
<div class="qds-controls flex-row">
  <qds-button importance="subdued" text="Open preferences"></qds-button>
  <qds-button importance="subdued" text="Cancel"></qds-button>
  <div class="qds-controls qds-related flex flex-row">
    <qds-button text="Previous"></qds-button>
    <qds-button importance="emphasized" text="Next"></qds-button>
  </div>
</div>

Additional options

Disabled

Use the disabled attribute to disable a button. Clicks will be suppressed until the disabled state is removed.

Loading...
Live Editor
<div class="qds-controls qds-related flex-row">
  <qds-button importance="standard" text="Standard" disabled></qds-button>
  <qds-button importance="emphasized" text="Emphasized" disabled></qds-button>
  <qds-button importance="subdued" text="Subdued" disabled></qds-button>
  <qds-button importance="destructive" text="Destructive" disabled></qds-button>
</div>

Loading state

Accessibility

badge-description

Use the badge-description attribute to give more context to screen readers when a badge is being used.

In the following example, this button's badge will be read by screen readers as "2 new notifications".

Loading...
Live Editor
<qds-button badge="2" badge-description="new notifications"></qds-button>

aria-haspopup

Use the aria-haspopup attribute to indicate the type of interactive popup element that can be triggered by the qds-button.

By default the button will set the attribute aria-expanded="true" but the popup type has to be defined between the following options: menu, listbox, tree, grid, dialog or true.

See the aria-haspopup MDN documentation for an in-depth introduction.

Implementation tips

href property

It's often helpful to have a button that works like a link. This is possible by setting the href attribute, which will make the component render an <a> under the hood. This gives you all the default link behavior the browser provides (e.g. CMD/CTRL/SHIFT + CLICK) and exposes the target and download attributes.

Loading...
Live Editor
<div class="qds-controls qds-related flex-row">
  <qds-button href="https://example.com/" text="Link"></qds-button>
  <qds-button href="https://example.com/" target="_blank" text="New Window"></qds-button>
  <qds-button href="/img/logo.svg" download="quartz.svg" text="Download"></qds-button>
  <qds-button href="https://example.com/" disabled text="Disabled"></qds-button>
</div>

Custom width

By default, buttons size themselves to fit their content. Use the width CSS property as you usually do to set a custom width.

For example, you can use the w-full or flex-1 utility classes from our Tailwind preset:

Loading...
Live Editor
<div class="qds-controls qds-related">
  <qds-button text="Default fitting behavior"></qds-button>
  <qds-button text="Full width" class="w-full"></qds-button>
  <div class="qds-controls qds-related flex-row w-full">
    <qds-button class="flex-1" text="Flex"></qds-button>
    <qds-button class="flex-1" text="Layout"></qds-button>
    <qds-button class="flex-1" text="Buttons"></qds-button>
  </div>
</div>

This is useful for making buttons span the full width of their container on smaller screens.

Submit a form

Quartz button follows the native HTML button's behavior.

When placed inside a <form>, the button will submit the form by default:

Loading...
Live Editor
<form class="qds-controls qds-related">
  <qds-checkbox required text="I am required"></qds-checkbox>
  <qds-button text="Proceed"></qds-button>
</form>

To prevent this behavior, set type="button" on the button:

Loading...
Live Editor
<form class="qds-controls qds-related">
  <qds-checkbox required text="I am required"></qds-checkbox>
  <div class="qds-controls qds-related flex-row">
    <qds-button text="No effect" type="button"></qds-button>
    <qds-button text="Submit"></qds-button>
  </div>
</form>

Importing

Note: if you're using the lazy loader to load Quartz components, you can ignore this section.

To import this component from the public jsDeliver CDN using a JavaScript import:

import { defineCustomElementQdsRadio } from 'https://cdn.jsdelivr.net/npm/@quartzds/core@next+esm'
defineCustomElementQdsRadio()

Component reference

Properties

Attribute / PropertyTypeDescriptionDefault
action
"dropdown" | "dropdown-close" | "next" | undefined

The name of the action icon to render.

undefined
badge
string | undefined

The button's badge text.

undefined
badge-description / badgeDescription
string | undefined

Adds accessible text to the badge that will be used by screen readers.

undefined
disabled
boolean | undefined

Prevents the button from being interacted with: it cannot be pressed or focused.

undefined
download
string | undefined

Tells the browser to download the linked file as this filename. Only used when href is set.

undefined
form
string | undefined

The <form> element to associate the button with (its form owner).

The value of this attribute must be the id of a <form> in the same document. If this attribute is not set, the <button> is associated with its ancestor <form> element, if any.

This attribute lets you associate <button> elements to <form>s anywhere in the document, not just inside a <form>. It can also override an ancestor <form> element.

undefined
formaction / formAction
string | undefined

The URL that processes the information submitted by the button. Overrides the action attribute of the button's form owner. Does nothing if there is no form owner.

undefined
formmethod / formMethod
"dialog" | "get" | "post" | undefined

If the button is a submit button (it's inside/associated with a <form> and doesn't have type="button"), this attribute specifies the HTTP method used to submit the form, or dialog which won't submit the form. Possible values:

  • get: The form data are appended to the form's action URL, with a ? as a separator, and the resulting URL is sent to the server. Use this method when the form has no side effects, like search forms.
  • post: The data from the form are included in the body of the HTTP request when sent to the server. Use when the form contains information that shouldn't be public, like login credentials.
  • dialog: Close the dialog box in which the button finds itself, if any, and do not submit the button's form owner.

If specified, this attribute overrides the method attribute of the button's form owner.

undefined
formnovalidate / formNoValidate
boolean

If the button is a submit button, this attribute specifies that the form is not to be validated when it is submitted. If this attribute is specified, it overrides the novalidate attribute of the button's form owner.

false
formtarget / formTarget
"_blank" | "_parent" | "_self" | "_top" | string & Record<never, never>

If the button is a submit button, this attribute is an author-defined name or standardized, underscore-prefixed keyword indicating where to display the response from submitting the form. This is the name of, or keyword for, a browsing context (a tab, window, or <iframe>). If this attribute is specified, it overrides the target attribute of the button's form owner. The following keywords have special meanings:

  • _blank: Load the response into a new unnamed browsing context — usually a new tab or window, depending on the user's browser settings.
  • _parent: Load the response into the parent browsing context of the current one. If there is no parent, this option behaves the same way as _self.
  • _self: Load the response into the same browsing context as the current one.
  • _top: Load the response into the top-level browsing context (that is, the browsing context that is an ancestor of the current one, and has no parent). If there is no parent, this option behaves the same way as _self.
'_self'
href
string | undefined

When set, the underlying button will be rendered as an <a> with this href instead of a <button>.

undefined
icon-library / iconLibrary
string

The name of a registered icon library.

'default'
icon-name / iconName
string | undefined

The name of the icon to render.

Available names depend on the icon library being used.

undefined
importance
"emphasized" | "standard" | "subdued" | undefined

The button's importance.

'standard'
name
string | undefined

The name of the button, submitted as a pair with the button's value as part of the form data, when that button is used to submit the form. Ignored when href is set.

undefined
popup-type / popupType
"dialog" | "grid" | "menu" | "tree" | "true" | undefined

Indicates the type of interactive popup element that can be triggered by the qds-button.

undefined
rel
string | undefined

When href is define and the button act as a link (<a>), the rel will be added to the element.

'noopener'
size
"large" | "small" | "standard" | undefined

The button's size.

'standard'
target
"_blank" | "_parent" | "_self" | "_top" | string & Record<never, never> | undefined

Where to display the linked URL, as the name for a browsing context (a tab, window, or <iframe>. The following keywords have special meanings for where to load the URL:

  • _blank: usually a new tab, but users can configure browsers to open a new window instead.
  • _parent: the parent browsing context of the current one. If no parent, behaves as _self.
  • _self: the current browsing context.
  • _top: the topmost browsing context (the "highest" context that's an ancestor of the current one). If no ancestors, behaves as _self.
undefined
text
string | undefined

The button's text.

undefined
type
"button" | "reset" | "submit" | undefined

The type of button.

button: The button has no default behavior, and does nothing when pressed by default. It can have client-side scripts listen to the element's events, which are triggered when the events occur.

submit: The button submits the form data to the server. This is the default if the attribute is not specified for buttons associated with a <form>, or if the attribute is an empty or invalid value.

reset: The button resets all the controls to their initial values.

undefined
value
string | undefined

Defines the value associated with the button's name when it's submitted with the form data. This value is passed to the server in params when the form is submitted using this button. Ignored when href is set.

undefined
variant
"destructive" | "hero" | undefined

The button's variant.

undefined

Events

EventTypeDescriptionBubblesCancelableComposedqdsBlur
{ readonly relatedTarget: EventTarget | null; }

Emitted when the button loses focus.

qdsFocus
{ readonly relatedTarget: EventTarget | null; }

Emitted when the button gains focus.