Skip to main content

Button Ready

Buttons are used for interface actions. They default to appearance that has dark text with gray border. Primary style should be used only once per view for main call-to-action.

Users generally expect buttons to submit data or take action, and for links to navigate. If navigation is required for the button, use the url prop. The control will then output an anchor styled as a button, instead of an HTML button.

Examples #

Open in new window
<duet-button variation="primary">Primary button</duet-button>

<script>
// Select the above button
var button = document.querySelector("duet-button")

// Listen for clicks in the button
button.addEventListener("click", function (e) {
console.log("Button clicked", e)
})

// Listen for focus in the button
button.addEventListener("duetFocus", function (e) {
console.log("Focus detected", e)
})

// Listen for blur in the button
button.addEventListener("duetBlur", function (e) {
console.log("Blur detected", e)
})
</script>
Open in new window
<duet-button variation="primary" icon="navigation-arrow-left" fixed> With icon on left </duet-button>
Open in new window
<duet-button variation="primary" icon="navigation-arrow-right" fixed icon-right> With icon on right </duet-button>
Open in new window
<duet-button padding="none" margin="none" variation="plain" icon="action-arrow-left-small" icon-size="small" fixed>
Previous
</duet-button>

<duet-spacer direction="horizontal" size="x-large"></duet-spacer>

<duet-button
padding="none"
margin="none"
variation="plain"
icon="action-arrow-right-small"
icon-right
icon-size="small"
fixed
>

Next
</duet-button>
Open in new window
<duet-button variation="primary" loading>This button is loading…</duet-button>
<duet-button variation="secondary" loading>This button is loading…</duet-button>
<duet-button variation="default" loading>This button is loading…</duet-button>
Open in new window
<duet-button variation="primary" expand> Expand button </duet-button>
Open in new window
<duet-button variation="secondary"> Secondary button </duet-button>
Open in new window
<duet-button>Default button</duet-button>
Open in new window
<div class="duet-background-secondary-turva duet-p-x-large duet-mt-large duet-radius-default">
<duet-button variation="negative" margin="none"> Negative button </duet-button>
</div>
Open in new window
<duet-button variation="destructive-primary">Destructive primary button</duet-button><br/>
<duet-button variation="destructive-secondary">Destructive secondary button</duet-button><br/>
Open in new window
<duet-button variation='square' fixed>1</duet-button>
<duet-button variation='square' fixed>2</duet-button>
<duet-button variation='square' fixed negative>3</duet-button>
<duet-button variation='square' fixed>4</duet-button>
Open in new window
<duet-button disabled> Disabled default button </duet-button>
<duet-button variation="primary" disabled> Disabled primary button </duet-button>
Open in new window
<duet-button variation="plain" icon="navigation-arrow-left"> Plain button </duet-button>
Open in new window
<duet-button
padding="none"
margin="none"
variation="plain"
icon="action-arrow-down-small"
icon-size="small"
icon-right
fixed
>

Show more
</duet-button>

<br />

<duet-button
padding="none"
margin="none"
variation="plain"
icon="action-arrow-up-small"
icon-size="small"
icon-right
fixed
>

Show less
</duet-button>
Open in new window
<duet-grid responsive breakpoint="x-large" alignment="center">
<duet-grid-item>
<duet-button size="small" variation="primary" margin="none">Primary button</duet-button>
</duet-grid-item>
<duet-grid-item>
<duet-button size="small" variation="secondary" margin="none">Secondary button</duet-button>
</duet-grid-item>
<duet-grid-item>
<duet-button size="small" variation="secondary" margin="none" icon="action-add-circle"
>Secondary button with icon</duet-button
>

</duet-grid-item>
<duet-grid-item>
<duet-button size="small" margin="none">Default button</duet-button>
</duet-grid-item>
<duet-grid-item>
<div style="display: inline-block" class="duet-background-secondary-turva duet-p-small duet-radius-default">
<duet-button size="small" variation="negative" margin="none">Negative button</duet-button>
</div>
</duet-grid-item>
<duet-grid-item>
<duet-button size="small" variation="destructive" margin="none">Destructive button</duet-button>
</duet-grid-item>
<duet-grid-item>
<duet-button size="small" variation="destructive" icon="action-delete" margin="none"
>Destructive button with icon</duet-button
>

</duet-grid-item>
<duet-grid-item>
<duet-button size="small" disabled margin="none">Disabled button</duet-button>
</duet-grid-item>
</duet-grid>
Open in new window
<duet-heading level="h3" visual-level="h5" border>Valitse aika</duet-heading>
<duet-spacer></duet-spacer>

<duet-fieldset label="Aamupäivä">
<duet-button variation="secondary" size="small" accessible-label="Tapaa kello 10:00">
10:00 <span class="duet-ml-xx-small duet-font-weight-normal">60 min</span>
</duet-button>
<duet-button variation="secondary" size="small" accessible-label="Tapaa kello 10:30">
10:30 <span class="duet-ml-xx-small duet-font-weight-normal">60 min</span>
</duet-button>
<duet-button variation="secondary" size="small" accessible-label="Tapaa kello 11:00">
11:00 <span class="duet-ml-xx-small duet-font-weight-normal">60 min</span>
</duet-button>
<duet-button variation="secondary" size="small" accessible-label="Tapaa kello 11:30">
11:30 <span class="duet-ml-xx-small duet-font-weight-normal">60 min</span>
</duet-button>
<duet-fieldset>
<duet-fieldset label="Iltapäivä">
<duet-button variation="secondary" size="small" accessible-label="Tapaa kello 12:00">
12:00 <span class="duet-ml-xx-small duet-font-weight-normal">60 min</span>
</duet-button>
<duet-button variation="secondary" size="small" accessible-label="Tapaa kello 12:30">
12:30 <span class="duet-ml-xx-small duet-font-weight-normal">60 min</span>
</duet-button>
<duet-button variation="secondary" size="small" accessible-label="Tapaa kello 13:00">
13:00 <span class="duet-ml-xx-small duet-font-weight-normal">60 min</span>
</duet-button>
<duet-button variation="secondary" size="small" accessible-label="Tapaa kello 13:30">
13:30 <span class="duet-ml-xx-small duet-font-weight-normal">60 min</span>
</duet-button>
<duet-button variation="secondary" size="small" accessible-label="Tapaa kello 14:00">
14:00 <span class="duet-ml-xx-small duet-font-weight-normal">60 min</span>
</duet-button>
<duet-button variation="secondary" size="small" accessible-label="Tapaa kello 14:30">
14:30 <span class="duet-ml-xx-small duet-font-weight-normal">60 min</span>
</duet-button>
<duet-button variation="secondary" size="small" accessible-label="Tapaa kello 15:00">
15:00 <span class="duet-ml-xx-small duet-font-weight-normal">60 min</span>
</duet-button>
<duet-button variation="secondary" size="small" accessible-label="Tapaa kello 15:30">
15:30 <span class="duet-ml-xx-small duet-font-weight-normal">60 min</span>
</duet-button>
</duet-fieldset>

<duet-fieldset label="Ilta">
<duet-button variation="secondary" size="small" accessible-label="Tapaa kello 16:00">
16:00 <span class="duet-ml-xx-small duet-font-weight-normal">60 min</span>
</duet-button>
<duet-button variation="secondary" size="small" accessible-label="Tapaa kello 16:30">
16:30 <span class="duet-ml-xx-small duet-font-weight-normal">60 min</span>
</duet-button>
<duet-fieldset>
<duet-visually-hidden>
<span class="aria-live" aria-live="polite"></span>
</duet-visually-hidden>

<script>
// Select the above buttons
var timeSlots = document.querySelectorAll("duet-button")

// When an available time slot is clicked, make it active
timeSlots.forEach(function (button) {
button.addEventListener("click", function () {
timeSlots.forEach(function (el) {
el.variation = "secondary"
})
button.variation = "primary"

// This part makes sure screen readers read out what time slot was selected.
var aria = document.querySelector(".aria-live")
aria.innerHTML = "Olet valinnut tapaamisajaksi kello " + button.textContent + "."
})
})
</script>
</duet-fieldset></duet-fieldset
></duet-fieldset
></duet-fieldset
>
Open in new window
<form>
<duet-input name="name" label="Name" value="Test"></duet-input>
<duet-grid>
<duet-button variation="destructive" name="which" value="delete" submit> Delete </duet-button>
<duet-button variation="primary" name="which" value="add" submit> Add </duet-button>
</duet-grid>
</form>
Open in new window
<duet-grid responsive breakpoint="x-large" alignment="center">
<duet-grid-item style="padding: 40px;">
<duet-button size="small" variation="primary" margin="none">Primary button</duet-button>
<duet-button size="small" variation="secondary" margin="none">Secondary button</duet-button>
<duet-button size="small" variation="secondary" margin="none" icon="action-add-circle"
>
Secondary button with icon</duet-button>
<duet-button size="small" margin="none">Default button</duet-button>
<div style="display: inline-block" class="duet-background-secondary-turva duet-p-small duet-radius-default">
<duet-button size="small" variation="negative" margin="none">Negative button</duet-button>
</div>
<duet-button size="small" variation="destructive-primary" margin="none">Destructive-primary button</duet-button>
<duet-button size="small" variation="destructive-primary" icon="action-delete" margin="none">Destructive-primary button with icon</duet-button>
<duet-button size="small" variation="destructive-secondary" margin="none">Destructive-secondary button</duet-button>
<duet-button size="small" variation="destructive-secondary" icon="action-delete" margin="none">Destructive-secondary button with icon</duet-button>
<duet-button size="small" disabled margin="none">Disabled button</duet-button>
<duet-button size="small" icon-size="medium-small" variation="plain" margin="none" external url="http://some.link">plain button</duet-button>
<duet-button size="small" variation="square" fixed negative margin="none">1</duet-button>
</duet-grid-item>

<duet-grid-item style="background-color: black;padding: 40px;">
<duet-button size="small" negative variation="primary" margin="none">Primary button</duet-button>
<duet-button size="small" negative variation="secondary" margin="none">Secondary button</duet-button>
<duet-button size="small" negative variation="secondary" margin="none" icon="action-add-circle"
>
Secondary button with icon</duet-button>
<duet-button size="small" negative margin="none">Default button</duet-button>
<div style="display: inline-block" class="duet-background-secondary-turva duet-p-small duet-radius-default">
<duet-button size="small" negative variation="negative" margin="none">Negative button</duet-button>
</div>
<duet-button size="small" negative variation="destructive-primary" margin="none">Destructive-primary button</duet-button>
<duet-button size="small" negative variation="destructive-primary" icon="action-delete" margin="none"
>
Destructive-primary button with icon</duet-button>
<duet-button size="small" negative variation="destructive-secondary" margin="none">Destructive-secondary button</duet-button>
<duet-button size="small" negative variation="destructive-secondary" icon="action-delete" margin="none"
>
Destructive-secondary button with icon</duet-button>
<duet-button size="small" negative disabled margin="none">Disabled button</duet-button>
<duet-button size="small" icon-size="medium-small" negative variation="plain" margin="none" external url="http://some.link">plain button</duet-button>
<duet-button size="small" variation="square" fixed negative margin="none">1</duet-button>
</duet-grid-item>


<duet-grid-item style="background-color: rgb(50,50,50);padding: 40px;">
<duet-button size="small" negative variation="primary" margin="none">Primary button</duet-button>
<duet-button size="small" negative variation="secondary" margin="none">Secondary button</duet-button>
<duet-button size="small" negative variation="secondary" margin="none" icon="action-add-circle"
>
Secondary button with icon</duet-button>
<duet-button size="small" negative margin="none">Default button</duet-button>
<div style="display: inline-block" class="duet-background-secondary-turva duet-p-small duet-radius-default">
<duet-button size="small" negative variation="negative" margin="none">Negative button</duet-button>
</div>
<duet-button size="small" negative variation="destructive-primary" margin="none">Destructive-primary button</duet-button>
<duet-button size="small" negative variation="destructive-primary" icon="action-delete" margin="none"
>
Destructive-primary button with icon</duet-button>
<duet-button size="small" negative variation="destructive-secondary" margin="none">Destructive-secondary button</duet-button>
<duet-button size="small" negative variation="destructive-secondary" icon="action-delete" margin="none"
>
Destructive-secondary button with icon</duet-button>
<duet-button size="small" negative disabled margin="none">Disabled button</duet-button>
<duet-button size="small" icon-size="medium-small" negative variation="plain" margin="none" external url="http://some.link">plain button</duet-button>
<duet-button size="small" variation="square" fixed negative margin="none">1</duet-button>
</duet-grid-item>
</duet-grid>

<duet-grid responsive breakpoint="x-large" alignment="center">
<duet-grid-item style="padding: 40px;">
<duet-button variation="primary" margin="none">Primary button</duet-button>
<duet-button variation="secondary" margin="none">Secondary button</duet-button>
<duet-button variation="secondary" margin="none" icon="action-add-circle"
>
Secondary button with icon</duet-button>
<duet-button margin="none">Default button</duet-button>
<div style="display: inline-block" class="duet-background-secondary-turva duet-p-small duet-radius-default">
<duet-button variation="negative" margin="none">Negative button</duet-button>
</div>
<duet-button variation="destructive-primary" margin="none">Destructive-primary button</duet-button>
<duet-button variation="destructive-primary" icon="action-delete" margin="none">Destructive-primary button with icon</duet-button>
<duet-button variation="destructive-secondary" margin="none">Destructive-secondary button</duet-button>
<duet-button variation="destructive-secondary" icon="action-delete" margin="none">Destructive-secondary button with icon</duet-button>
<duet-button disabled margin="none">Disabled button</duet-button>
<duet-button icon-size="medium-small" variation="plain" margin="none" external url="http://some.link">plain button</duet-button>
<duet-button size="small" variation="square" fixed negative margin="none">1</duet-button>
</duet-grid-item>

<duet-grid-item style="background-color: black;padding: 40px;">
<duet-button negative variation="primary" margin="none">Primary button</duet-button>
<duet-button negative variation="secondary" margin="none">Secondary button</duet-button>
<duet-button negative variation="secondary" margin="none" icon="action-add-circle"
>
Secondary button with icon</duet-button>
<duet-button negative margin="none">Default button</duet-button>
<div style="display: inline-block" class="duet-background-secondary-turva duet-p-small duet-radius-default">
<duet-button negative variation="negative" margin="none">Negative button</duet-button>
</div>
<duet-button negative variation="destructive-primary" margin="none">Destructive-primary button</duet-button>
<duet-button negative variation="destructive-primary" icon="action-delete" margin="none"
>
Destructive-primary button with icon</duet-button>
<duet-button negative variation="destructive-secondary" margin="none">Destructive-secondary button</duet-button>
<duet-button negative variation="destructive-secondary" icon="action-delete" margin="none"
>
Destructive-secondary button with icon</duet-button>
<duet-button negative disabled margin="none">Disabled button</duet-button>
<duet-button icon-size="medium-small" negative variation="plain" margin="none" external url="http://some.link">plain button</duet-button>
<duet-button variation="square" fixed negative margin="none">1</duet-button>
</duet-grid-item>


<duet-grid-item style="background-color: rgb(50,50,50);padding: 40px;">
<duet-button negative variation="primary" margin="none">Primary button</duet-button>
<duet-button negative variation="secondary" margin="none">Secondary button</duet-button>
<duet-button negative variation="secondary" margin="none" icon="action-add-circle"
>
Secondary button with icon</duet-button>
<duet-button negative margin="none">Default button</duet-button>
<div style="display: inline-block" class="duet-background-secondary-turva duet-p-small duet-radius-default">
<duet-button negative variation="negative" margin="none">Negative button</duet-button>
</div>
<duet-button negative variation="destructive-primary" margin="none">Destructive-primary button</duet-button>
<duet-button negative variation="destructive-primary" icon="action-delete" margin="none"
>
Destructive-primary button with icon</duet-button>
<duet-button negative variation="destructive-secondary" margin="none">Destructive-secondary button</duet-button>
<duet-button negative variation="destructive-secondary" icon="action-delete" margin="none"
>
Destructive-secondary button with icon</duet-button>
<duet-button negative disabled margin="none">Disabled button</duet-button>
<duet-button icon-size="medium-small" negative variation="plain" margin="none" external url="http://some.link">plain button</duet-button>
<duet-button variation="square" fixed negative margin="none">1</duet-button>
</duet-grid-item>
</duet-grid>

Properties #

Property Attribute Description Type Default
accessibleActiveDescendant accessible-active-descendant Indicates the id of a related component’s visually focused element. string undefined
accessibleControls accessible-controls Use this property to add an aria-controls attribute to the button. Use the attribute to point to the unique id of the content that the button manages. string undefined
accessibleDescribedBy accessible-described-by Indicates the id of a component that describes the button. string undefined
accessibleDescription accessible-description Aria description the button string undefined
accessibleDetails accessible-details Details of the component string undefined
accessibleExpanded accessible-expanded If a button expands or collapses adjacent content, then use the ariaExpanded prop to add the aria-expanded attribute to the button. Set the value to convey the current expanded (true) or collapsed (false) state of the content. boolean undefined
accessibleLabel accessible-label Adds accessible label for the button that is only shown for screen readers. Typically, this label text replaces the visible text on the button for users who use assistive technology. string undefined
accessibleLabelExternal accessible-label-external Adds accessible label for tooltip that is shown in external link (url & external have both been set) string getLocaleString(this.accessibleLabelExternalDefaults)
accessibleLabelExternalDefaults accessible-label-external-default Property to change accessibleLabelExternal defaults on the component. normally you would handle these strings on an application level and override accessibleLabelExternal when needed DuetLangObject | string DuetStringsExternalDefaults
accessibleLabelLoading accessible-label-loading Adds accessible label for button in "loading" state string getLocaleString(this.accessibleLabelLoadingDefaults)
accessibleLabelLoadingDefaults accessible-label-loading-default Property to change accessibleLabelLoading defaults on the component. normally you would handle these strings on an application level and override accessibleLabelLoading when needed DuetLangObject | string DuetStringsLoadingDefaults
accessibleLabelledBy accessible-labelled-by String of id's that indicate alternative labels elements string undefined
accessibleOwns accessible-owns Indicates the id of a component owned by the button. string undefined
accessiblePopup accessible-popup Use this property to add an aria-haspopup attribute to a button, if you are using it as a menu button. string "false"
accessiblePressed accessible-pressed Tells screen reader the element is pressed. boolean undefined
centerText center-text Centers the text of a button boolean false
color color Custom color to be used for text, as a design token entered in camelCase or kebab-case. Example: "color-primary". string ""
disabled disabled Makes the button component disabled. This prevents users from being able to interact with the button, and conveys its inactive state to assistive technologies. boolean false
expand expand Expands the button to fill 100% of the container width. boolean false
external external Forces URL to open in a new browser tab. Used together with URL prop. boolean false
fixed fixed Keep the button fixed width even on mobile viewports. boolean false
icon icon Icon to display to the left of the button content. This is ignored/overridden when button is used as an external link. string ""
iconOnly icon-only Whether this button should use styles meant for displaying just an icon. boolean false
iconRight icon-right Show icon on the right side of the button content. boolean false
iconSize icon-size Icon size. "large" | "medium" | "medium-small" | "small" "medium"
identifier identifier Adds a unique identifier for the button. Please note that with this particular component this id is added inside Shadow DOM. If you need an id on the html element, use regular id attribute instead. string undefined
language language [DEPRECATED] this is now handled via the html lang tag, and is no longer used - kept to avoid breaking changes and ease unit testing

"en" | "fi" | "sv" getLanguage()
loading loading Loading state of the button boolean false
margin margin Controls the margin of the component. "auto" | "none" "auto"
name name The name of the button, which gets paired with the button's value when submitted as part of a form. Corresponds with the native HTML name attribute. string undefined
negative negative Negative variation, can be combined with Variation to produce negative versions boolean false
padding padding Controls the padding of the plain variation button - has no effect for other variations. "auto" | "none" "auto"
size size Button’s size. "medium" | "small" | "x-small" "medium"
submit submit Allows the button to submit a form. boolean false
theme theme Theme of the button. "" | "default" | "turva" ""
url url A destination to link to, rendered in the href attribute of a link. string undefined
value value The value of the button, which gets paired with the button's name when submitted as part of a form. Corresponds with the native HTML value attribute. string undefined
variation variation Style variation of the button. "default" | "destructive" | "destructive-primary" | "destructive-secondary" | "input-button-embedded" | "input-button-primary" | "input-button-secondary" | "negative" | "plain" | "primary" | "secondary" | "square" "default"
wrapping wrapping Controls the text wrapping. "auto" | "none" "auto"

Events #

Event Description Type
duetBlur Emitted when the button loses focus. CustomEvent<any>
duetFocus Emitted when the button has focus. CustomEvent<any>

Methods #

setFocus(options?: FocusOptions) => Promise<void> #

Sets focus on the specified duet-button. Use this method instead of the global
button.focus().

Parameters #

Name Type Description
options FocusOptions

Returns #

Type: Promise<void>


Usage #

This section includes guidelines for designers and developers about the usage of this component in different contexts.

When to use #

  • In general, buttons should be used for all interface actions that aren’t links to other views in the app.
  • When you need to provide a call-to-action for the user.
  • For form submit, cancel, edit, save and opening a modal.
  • Plain buttons, which look similar to links, are used for less commonly used actions such as “view settings.”

When not to use #

  • Avoid using buttons as links to other pages. Use Link component instead.
  • For navigation where the link often appears within or following a sentence.

Variations #

This section describes the different component variations, their purpose, and when to use each variation.

Name Purpose
default Default style is the most common button variation. Only switch to another variation if you need to adjust the visual weight of the element. Please note that the default style uses transparent background so that it works nicely on Duet’s light background gradients.
primary Primary style is reserved for the view’s main call-to-action. Should be used only once per view, e.g. for a submit action at the end of a form. This style also works on top of dark background or images.
secondary Secondary style should be used for secondary actions in a view. Most commonly used when there is already a primary action and we want to highlight another action with a different style.
negative Negative style is meant for dark backgrounds and to be used on top of illustrations.
destructive Destructive style should be used for actions that delete data or otherwise make it hard to revert the action.
plain Used for less important or less common actions.
disabled Used for actions that aren’t currently available or not available anymore.
loading Used to indicate progress when a button has been pressed and the action is still processing.

Accessibility #

This component has been validated to meet the WCAG 2.1 AA accessibility guidelines. You can find additional information regarding accessibility of this component below.

Additional considerations #


Integration

For integration, event and theming guidelines, please see Using Components. This documentation explains how to implement and use Duet’s components across different technologies like Angular, React or Vanilla JavaScript.

Integration guidelines


Tutorials

Follow these practical tutorials to learn how to build simple page layouts using Duet’s CSS Framework, Web Components and other features:

Tutorials

Building Layouts

Tutorials

Using CLI Tools

Tutorials

Creating Custom Patterns

Tutorials

Server Side Rendering

Tutorials

Sharing Prototypes

Tutorials

Usage With Markdown


Troubleshooting

If you experience any issues while using a component, please head over to the Support page for more guidelines and help.