Skip to main content

Stepper Ready

Stepper is used to create wizard-like workflows by dividing content into logical steps. The user can navigate backwards by clicking on the header of a completed step.

Examples #

Open in new window
<duet-stepper>
<duet-step heading="Your name">
<duet-fieldset margin="none">
<duet-input label="First name" expand></duet-input>
<duet-input label="Last name" expand></duet-input>
<duet-spacer></duet-spacer>
<duet-button margin="none" variation="primary" class="next">Next</duet-button>
</duet-fieldset>
</duet-step>

<duet-step heading="Favourite food">
<duet-fieldset margin="none">
<duet-radio-group responsive label="Choose" direction="vertical" value="pizza" name="group1">
<duet-radio value="pizza" label="Pizza"></duet-radio>
<duet-radio value="burger" label="Burger"></duet-radio>
<duet-radio value="salad" label="Salad"></duet-radio>
</duet-radio-group>
<duet-button margin="none" variation="primary" class="next">Next</duet-button>
</duet-fieldset>
</duet-step>

<duet-step heading="Final step">
<duet-fieldset margin="none">
<duet-textarea expand label="Write something about yourself" placeholder="Placeholder text"></duet-textarea>
</duet-fieldset>
</duet-step>
</duet-stepper>

<script>
var stepper = document.querySelector("duet-stepper")
var nextButtons = document.querySelectorAll("duet-button.next")

// when "next" button is clicked, advance to next step
nextButtons.forEach(function (button) {
button.addEventListener("click", function () {
stepper.selected++
})
})

// duetStepChange event is raised whenever a step heading is clicked
// when this happens, change to that step
stepper.addEventListener("duetStepChange", function (e) {
stepper.selected = e.detail.toStep
console.log("step change:", "from", e.detail.fromStep, "to", e.detail.toStep)
})
</script>
Open in new window
<duet-stepper>
<duet-step heading="Your name">
<div slot="heading-content">
<duet-caption margin="none"> The heading-content slot allows for additional content </duet-caption>
</div>
<duet-fieldset margin="none">
<duet-input label="First name" expand></duet-input>
<duet-input label="Last name" expand></duet-input>
<duet-spacer></duet-spacer>
<duet-button margin="none" variation="primary" class="next">Next</duet-button>
</duet-fieldset>
</duet-step>

<duet-step heading="Favourite food">
<duet-fieldset margin="none">
<duet-radio-group responsive label="Choose" direction="vertical" value="pizza" name="group1">
<duet-radio value="pizza" label="Pizza"></duet-radio>
<duet-radio value="burger" label="Burger"></duet-radio>
<duet-radio value="salad" label="Salad"></duet-radio>
</duet-radio-group>
<duet-button margin="none" variation="primary" class="next">Next</duet-button>
</duet-fieldset>
</duet-step>

<duet-step heading="Final step">
<duet-fieldset margin="none">
<duet-textarea expand label="Write something about yourself" placeholder="Placeholder text"></duet-textarea>
</duet-fieldset>
</duet-step>
</duet-stepper>

<script>
var stepper = document.querySelector("duet-stepper")
var nextButtons = document.querySelectorAll("duet-button.next")

nextButtons.forEach(function (button) {
button.addEventListener("click", function () {
stepper.selected++
})
})

stepper.addEventListener("duetStepChange", function (e) {
stepper.selected = e.detail.toStep
})
</script>
Open in new window
<duet-stepper>
<duet-step heading="First step">
<duet-fieldset margin="none">
<duet-input label="First name" expand></duet-input>
<duet-input label="Last name" expand></duet-input>
<duet-spacer></duet-spacer>
<duet-button margin="none" variation="primary" class="next">Next</duet-button>
</duet-fieldset>
</duet-step>

<duet-step heading="Second step">
<duet-fieldset margin="none">
<duet-paragraph
>
Try un-checking the checkbox below. If it is unchecked, you will be prevented from navigating to the first step
when you click on its heading.</duet-paragraph
>

<duet-checkbox checked label="Allow navigating backwards"></duet-checkbox>
</duet-fieldset>
</duet-step>
</duet-stepper>

<script>
var stepper = document.querySelector("duet-stepper")
var nextButton = document.querySelector("duet-button.next")

nextButton.addEventListener("click", function () {
stepper.selected++
})

stepper.addEventListener("duetStepChange", function (e) {
stepper.selected = e.detail.toStep
})

// This is purely for the purpose of this example.
var checkbox = document.querySelector("duet-checkbox")
checkbox.addEventListener("duetChange", function (e) {
stepper.backDisabled = !e.target.checked
})
</script>
Open in new window
<duet-stepper>
<duet-step heading="Your name">
<duet-fieldset margin="none">
<duet-input label="First and last name" expand></duet-input>
<duet-spacer></duet-spacer>
<duet-button margin="none" variation="primary" class="next">Next</duet-button>
</duet-fieldset>
</duet-step>
<duet-step heading="Favourite food">
<duet-fieldset margin="none">
<duet-radio-group responsive label="Choose" direction="vertical" value="pizza" name="group1">
<duet-radio value="pizza" label="Pizza"></duet-radio>
<duet-radio value="burger" label="Burger"></duet-radio>
<duet-radio value="salad" label="Salad"></duet-radio>
</duet-radio-group>
<duet-button margin="none" variation="primary" class="next">Next</duet-button>
</duet-fieldset>
</duet-step>
<duet-step heading="Final step">
<duet-fieldset margin="none">
<duet-textarea expand label="Write something about yourself" placeholder="Placeholder text"></duet-textarea>
</duet-fieldset>
</duet-step>
</duet-stepper>

<div class="duet-shadow-card duet-p-large duet-mb-large duet-radius-default">
<duet-grid alignment="center">
<duet-grid-item margin="none">
<div class="custom-icon duet-background-gray-darker duet-radius-circle">
<duet-icon name="messaging-checked-file" color="gray-lightest" margin="none" size="auto"></duet-icon>
</div>
</duet-grid-item>
<duet-grid-item margin="none" class="custom-grid-item">
<duet-heading margin="none" level="h4" color="gray-darker"> Additional custom step </duet-heading>
</duet-grid-item>
</duet-grid>
</div>

<style>
/* If you need to support IE11 use Sass tokens instead of CSS Variables */
.custom-grid-item {
align-self: center;
}
.custom-icon {
display: flex;
align-items: center;
justify-content: center;
margin-right: var(--space-small);
width: var(--size-step-small);
height: var(--size-step-small);
}
.custom-icon duet-icon {
width: var(--size-icon-x-small);
height: var(--size-icon-x-small);
}
@media (min-width: 36em) {
.custom-icon {
margin-right: var(--space-large);
margin-left: var(--space-x-small);
width: var(--size-step-medium);
height: var(--size-step-medium);
}
.custom-icon duet-icon {
width: var(--size-icon-small);
height: var(--size-icon-small);
}
}
</style>

<script>
var stepper = document.querySelector("duet-stepper")
var nextButtons = document.querySelectorAll("duet-button.next")

// when "next" button is clicked, advance to next step
nextButtons.forEach(function (button) {
button.addEventListener("click", function () {
stepper.selected++
})
})

// duetStepChange event is raised whenever a step heading is clicked
// when this happens, change to that step
stepper.addEventListener("duetStepChange", function (e) {
stepper.selected = e.detail.toStep
console.log("step change:", "from", e.detail.fromStep, "to", e.detail.toStep)
})
</script>

Properties #

Property Attribute Description Type Default
accessibleLive accessible-live Format of message used to announce current step when navigating between steps. The string {current} is replaced with current the step number. The string {total} is replaced with the total number of steps. string "Lista jossa {total} kohtaa. Olet kohdassa {current}."
backDisabled back-disabled Controls whether navigation back to previous steps is allowed or not. boolean false
margin margin Controls the margin of the component. "auto" | "none" "auto"
selected selected The index of the current step. number 0
theme theme Theme of the component. "" | "default" | "turva" ""

Events #

Event Description Type
duetStepChange Event emitted when the current step is changed. Can be cancelled to prevent the change. CustomEvent<{ component: "duet-stepper"; fromStep: number; toStep: number; }>

Usage #

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

When to use #

  • To create wizard-like workflows by dividing content into logical steps.
  • For insurance purchase flows.

When not to use #

  • For dividing simple forms into multiple steps. Use card component instead.

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.


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.