Helsinki Design System
Helsinki Design System
Getting started
Tutorials
Guidelines
Visual assets
Design tokens
Components
OverviewAccordionButtonPrinciplesAccessibilityUsage & variationsDemos & APICardCheckboxDate inputDialogDropdownFieldsetFooterIconKorosLoading spinnerLogoNavigationNotificationNumber inputPassword inputPhone inputRadio buttonSearch inputSelection groupStatus labelTabsTagText fieldsTime inputToggle buttonTooltip
Patterns
About
Contributing
Resources

Buttons

StableAccessible

Buttons are meant to make actions easily visible and understandable to the user. HDS offers different kinds of button variations which each suit for different needs.

Principles

  • Buttons are used to trigger an action. Be cautious when using buttons for navigating. In most cases, you should prefer links for this purpose. 
  • Button label should always describe the action that the buttons is going to trigger. A good practice is to start the label with a verb and use two-word labels at maximum.
  • Use provided button types to control the visual priority of the view. Priority of the button types is the following: Primary -> Secondary -> Supplementary.
  • In mobile screen sizes, use full-width buttons. In other sizes use buttons that scale according to their content.
  • Try to keep the amount of buttons in one view low. If there is a need for several actions in one view, consider using the smaller button variant.

Accessibility

  • It is advisable to use colour combinations provided by the implementation. These combinations are ensured to comply with WCAG AA requirements. When customising colours, refer to colour guidelines to ensure accessibility.
  • In most cases, prefer using normal size buttons over small buttons. Default sized buttons are easier for users to notice and press.
  • HDS Buttons (even the Small variant) comply with WCAG 2.5.5 Target Size (AAA) guideline. Customizing button sizes is not recommended.

Usage & variations

Primary button

A Primary button is reserved for the most important action on the screen. Primary action is usually either mandatory or essential for the user. Primary buttons are designed to clearly highlight the most important action, and therefore you should avoid having multiple primary buttons on one screen. For less important actions, consider using secondary or supplementary buttons instead.

Core code example:

<button type="button" class="hds-button hds-button--primary">
<span class="hds-button__label">Primary</span>
</button>

React code example:

<Button>Primary</Button>

Secondary button

Secondary buttons are used for actions which are not mandatory or essential for the user. Often screens will include multiple secondary buttons alongside one primary button.

Core code example:

<button type="button" class="hds-button hds-button--secondary">
<span class="hds-button__label">Secondary</span>
</button>

React code example:

<Button variant="secondary">Secondary</Button>

Supplementary button

Supplementary buttons can be used in similar cases as secondary buttons. However, supplementary buttons are meant for actions which are intentionally wanted to be less visible to the user. These kind of actions include i.e. cancel and dismiss functionalities.

Note! Since supplementary buttons do not have borders, an accompanying icon is required to clearly distinguish them from links and passive text elements.

Core code example:

<button type="button" class="hds-button hds-button--supplementary">
<span aria-hidden="true" class="hds-icon hds-icon--trash"></span>
<span class="hds-button__label">Supplementary</span>
</button>

React code example:

<Button variant="supplementary" iconLeft={<IconTrash />}>Supplementary</Button>

Icon buttons

Icons can be added to buttons to make the action easier to understand. Sometimes it can also be beneficial to add icons to make important actions more distinguishable. It is not recommended to use buttons with icons without text label because users interpret icons in different ways. More information on icon usage in the icon guidelines.

Core code example:

<button type="button" class="hds-button hds-button--primary">
<span aria-hidden="true" class="hds-icon hds-icon--share"></span>
<span class="hds-button__label">Button</span>
</button>
<button type="button" class="hds-button hds-button--primary">
<span class="hds-button__label">Button</span>
<span aria-hidden="true" class="hds-icon hds-icon--angle-right"></span>
</button>
<button type="button" class="hds-button hds-button--primary">
<span aria-hidden="true" class="hds-icon hds-icon--share"></span>
<span class="hds-button__label">Button</span>
<span aria-hidden="true" class="hds-icon hds-icon--angle-right"></span>
</button>

React code example:

<Button iconLeft={<IconShare />}>Button</Button>
<Button iconRight={<IconAngleRight />}>Button</Button>
<Button iconLeft={<IconShare />} iconRight={<IconAngleRight />}>Button</Button>

Small buttons

It is recommended to use the standard button size in most cases. If there is a big number of actions in the same view, small buttons can be used instead of the normal sized buttons. Small buttons can be especially useful in mobile screen sizes to ensure uncluttered view with multiple available actions.

Core code example:

<button type="button" class="hds-button hds-button--primary hds-button--small">
<span class="hds-button__label">Button</span>
</button>
<button type="button" class="hds-button hds-button--secondary hds-button--small">
<span class="hds-button__label">Button</span>
</button>
<button type="button" class="hds-button hds-button--supplementary hds-button--small">
<span class="hds-button__label">Button</span>
</button>

React code example:

<Button size="small">Primary</Button>
<Button variant="secondary" size="small">Secondary</Button>
<Button variant="supplementary" size="small">Supplementary</Button>

Utility buttons

If required, to achieve clearer user interface, you may also use additional utility colors. Different visual styles of these buttons can be used to better inform users of destructive or dangerous actions. To comply with WCAG requirement 1.4.1 Use of Color, these colors are more accessible when paired with an icon.

Core code example:

<button type="button" class="hds-button hds-button--success">
<span class="hds-button__label">Button</span>
</button>
<button type="button" class="hds-button hds-button--danger">
<span class="hds-button__label">Button</span>
</button>

React code example:

<Button variant="success">Success</Button>
<Button variant="danger">Danger</Button>

React code example:

<Button size="small">Primary</Button>
<Button variant="secondary" size="small">Secondary</Button>
<Button variant="supplementary" size="small">Supplementary</Button>

Loading buttons

If an action triggered by the button press is not immediate, a loading button state should be shown to the user to indicate the loading period.

When the loading action is triggered at the button press, the button will change its state to loading. After the loading is complete, either the next page loads or if the page stays the same, you should use other methods (such as notifications) to indicate the loading result.

Note! It is not recommended to use Supplementary buttons for loading actions since they can be hard to the user to differenciate from the loading state button.

Click the button to see loading button state in action. When loading is completed, a toast notification is shown to indicate the success.

Core code example:

Feature not supported in hds-core!

React code example:

{() => {
const [isLoading, setIsLoading] = React.useState(false);
const [showNotification, setShowNotification] = React.useState(false);
React.useEffect(() => {
let timeout;
if (isLoading) {
timeout = setTimeout(() => {
setShowNotification(true);
setIsLoading(false);
}, 2000);
}
return () => {
clearTimeout(timeout);
};
}, [isLoading]);
return (
<>
<Button
isLoading={isLoading}
loadingText="Saving form changes"
onClick={() => {
setShowNotification(false);
setIsLoading(true);
}}>
Save form
</Button>
{showNotification
&& <Notification
key={new Date().toString()}
position="top-right"
displayAutoCloseProgress={false}
autoClose
dismissible
label="Form saved!"
type="success"
onClose={() => {
setShowNotification(false)
}}>
Saving your form was successful.
</Notification>}
</>
)
}}

Demos & API

Core

Buttons in hds-core

React

Buttons in hds-react

Button API