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">
Destructive button
</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-label>Small buttons shouldn’t be combined with icons or similar:</duet-label>
<duet-spacer></duet-spacer>
<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" 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" 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>

<div class="timeslots">

<duet-label>Aamupäivä</duet-label>
<duet-spacer size="xx-small"></duet-spacer>

<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-spacer size="x-small"></duet-spacer>
<duet-label>Iltapäivä</duet-label>
<duet-spacer size="xx-small"></duet-spacer>

<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-spacer size="x-small"></duet-spacer>
<duet-label>Ilta</duet-label>
<duet-spacer size="xx-small"></duet-spacer>

<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>

</div>

<duet-visually-hidden>
<span class="aria-live" aria-live="polite"></span>
</duet-visually-hidden>

<script>
// Select the above buttons
var timeSlots = document.querySelectorAll(".timeslots 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>

Properties #

Property Attribute Description Type Default
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
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 false
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
accessiblePressed accessible-pressed Tells screen reader the element is pressed. 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. 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" | "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
loading loading Loading state of the button boolean false
margin margin Controls the margin of the component. "auto" | "none" "auto"
padding padding Controls the padding of the component. "auto" | "none" "auto"
size size Button’s size. "medium" | "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
variation variation Style variation of the button. "default" | "destructive" | "negative" | "plain" | "primary" | "secondary" "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() => Promise<void> #

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

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.



Tutorials

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

Tutorials

Abstract

Tutorials

Building Layouts

Tutorials

Using CLI Tools

Tutorials

Creating Custom Patterns

Tutorials

Server Side Rendering

Tutorials

Sharing Prototypes

Tutorials

Usage With Markdown

Tutorials

VS Code

Tutorials

Zeplin


Troubleshooting

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