States
| Data Attribute | Example |
|---|---|
| data-state="completed" |
✓
Completed
2
Next
|
| data-state="active" |
1
Active
2
Next
|
| data-state="upcoming" |
1
Upcoming
2
Upcoming
|
| data-state="error" |
✓
Done
2
Error
|
Variants
| Class | Example |
|---|---|
| .mdst-stepper |
✓
Account
2
Profile
3
Review
4
Confirm
|
| .mdst-stepper--vertical |
✓
Account
2
Profile
3
Review
4
Confirm
|
| .mdst-stepper--compact |
✓
Account
2
Profile
3
Review
4
Confirm
|
Examples
Checkout flow — step 2 active
✓
Cart
2
Shipping
3
Payment
4
Done
Error on step 2
✓
Cart
!
Shipping
3
Payment
4
Done
Vertical — step 3 active
✓
Select plan
✓
Create account
3
Enter payment
4
Confirmation
Interactive Demo
This demo uses vanilla JS to toggle data-state attributes. The JavaScript below is
not part of modest-ui — it’s here to show how the CSS responds to state changes. Bring whatever JS you
want.
1
Account
2
Profile
3
Review
4
Confirm
Demo source
const steps = document.querySelectorAll("#demo-stepper .mdst-stepper-step");
let current = 0;
function update() {
steps.forEach((step, i) => {
if (i < current) {
step.dataset.state = "completed";
step.querySelector(".mdst-stepper-indicator").textContent = "\u2713";
} else if (i === current) {
step.dataset.state = "active";
step.querySelector(".mdst-stepper-indicator").textContent = String(i + 1);
} else {
step.dataset.state = "upcoming";
step.querySelector(".mdst-stepper-indicator").textContent = String(i + 1);
}
});
backBtn.disabled = current === 0;
nextBtn.disabled = current >= steps.length;
}
nextBtn.addEventListener("click", () => { if (current < steps.length) { current++; update(); } });
backBtn.addEventListener("click", () => { if (current > 0) { current--; update(); } });
resetBtn.addEventListener("click", () => { current = 0; update(); });
Data Attribute Contract
<!-- Set data-state on each .mdst-stepper-step -->
data-state="completed" → Step is done (filled indicator, solid connector)
data-state="active" → Current step (bold indicator and label)
data-state="upcoming" → Not yet reached (muted indicator and label)
data-state="error" → Step has an error (error-colored indicator and label)
<!-- Your JS updates these attributes as the user progresses -->
step.dataset.state = "completed";
step.dataset.state = "active";
step.dataset.state = "error";
Usage
<!-- Horizontal stepper -->
<div class="mdst-stepper">
<div class="mdst-stepper-step" data-state="completed">
<div class="mdst-stepper-indicator">✓</div>
<div class="mdst-stepper-label">Account</div>
</div>
<div class="mdst-stepper-step" data-state="active">
<div class="mdst-stepper-indicator">2</div>
<div class="mdst-stepper-label">Profile</div>
</div>
<div class="mdst-stepper-step" data-state="upcoming">
<div class="mdst-stepper-indicator">3</div>
<div class="mdst-stepper-label">Review</div>
</div>
</div>
<!-- Vertical variant -->
<div class="mdst-stepper mdst-stepper--vertical">
<div class="mdst-stepper-step" data-state="completed">
<div class="mdst-stepper-indicator">✓</div>
<div class="mdst-stepper-label">Step 1</div>
</div>
<div class="mdst-stepper-step" data-state="active">
<div class="mdst-stepper-indicator">2</div>
<div class="mdst-stepper-label">Step 2</div>
</div>
</div>
<!-- Compact variant -->
<div class="mdst-stepper mdst-stepper--compact">
...
</div>
<!-- Error state -->
<div class="mdst-stepper-step" data-state="error">
<div class="mdst-stepper-indicator">!</div>
<div class="mdst-stepper-label">Failed</div>
</div>