Stepper
A flow in steps: numbered marks joined by lines that fill, a ring that glides to the current step and panels that slide in from the side they come from.
- enhancer
- wizard
- steps
- form
- progress
- onboarding
- since 0.2
Background Studio: tune it below, then copy the code
Your system asks for reduced motion: the demo shows its final state and nothing moves.
Live demo
Stepper example
Welcome aboard
Three short steps and your space is ready. You can change every answer later.
What should we call you?
Pick a home
Choose where new notes land first. Everything stays on this device until you share it.
All set
Press Complete and we will open your space with everything in place.
Welcome aboard
Three short steps and your space is ready. You can change every answer later.
What should we call you?
Pick a home
Choose where new notes land first. Everything stays on this device until you share it.
All set
Press Complete and we will open your space with everything in place.
Code
It follows the controls above: change an option and the code changes with it.
<link rel="stylesheet" href="/axi0/motion/motion.css?v=6">
<script src="/axi0/motion/motion.js?v=10" defer></script>
<div data-motion="stepper" aria-label="Create your space">
<section><h3>Welcome aboard</h3><p>Three short steps and your space is ready. You can change every answer later.</p></section>
<section><h3>What should we call you?</h3><label>Your name <input type="text" name="name" autocomplete="name" placeholder="Sam Rivera"></label></section>
<section><h3>Pick a home</h3><p>Choose where new notes land first. Everything stays on this device until you share it.</p></section>
<section><h3>All set</h3><p>Press Complete and we will open your space with everything in place.</p></section>
</div>
import { Stepper } from "./motion/react/Stepper";
<Stepper>Your content</Stepper>
<script setup lang="ts">
import Stepper from "./motion/vue/Stepper.vue";
</script>
<template>
<Stepper>Your content</Stepper>
</template>
const el = document.querySelector("#title");
el.dataset.motion = "stepper";
The wrappers: Stepper.tsx (React, TypeScript) and Stepper.vue (Vue). Both render the same attributes as the HTML; the loader does the rest.
Options
| Attribute | Default | What it does |
|---|---|---|
data-motion-layout | horizontal | marks in a row above the panel, or in a column beside it |
data-motion-back | Back | the Back button's text |
data-motion-next | Continue | the Continue button's text |
data-motion-finish | Complete | the last step's button text |
data-motion-label | Progress | the name of the list of steps |
Accessibility
- The marks are an ordered list inside a navigation landmark; the current one carries aria-current="step" and every mark's name says its number and title ("Step 2: What should we call you?"). - Marks of steps not reached yet are disabled (aria-disabled); finished steps can be visited again with Enter or Space. - Each panel is a labeled group ("Step 2 of 4: ..."). After Back or Continue, focus moves to the new panel and a polite announcement says where you are; panels out of view are inert. - Continue checks the step's own form fields first and shows the browser's message on the first one that is not valid. - Without JavaScript every step stays on the page, one after another. Reduced motion shows every state at once, with no movement, and stops anything that would move on its own. Frame loops and CSS animations pause off screen and in hidden tabs. Only transform, opacity and paint animate, so nothing around it moves.
Size
stepper.js is 2.8 KB gzip, with components-kit.js 3.9 KB it needs. A page loads the loader (2.7 KB) and core.js (1.4 KB) once, whatever it uses.