Stepper - National Design System

Step-by-step progress indicators for registration forms, onboarding flows, and service applications, with horizontal, vertical, and radial layouts that can switch responsively across breakpoints

Stepper Layouts

Three layouts render from one component: horizontal (default), vertical, and radial. Toggle the variant to preview each. The markup stays identical across variants; the progress ring and look-ahead text are part of the shared DOM and surface only in radial

Personal Information Identity details and contact information Next: Document Upload
Document Upload Upload required supporting documents Next: Review & Confirmation
Review & Confirmation Verify information before submission Next: Application Submitted
Application Submitted Confirmation and next steps

Responsive Stepper

A single stepper that morphs between variants as the viewport crosses breakpoints. Suited to flows that span mobile and desktop, where a compact radial on small screens should give way to a full vertical panel on desktop. Resize the window to see the transition

Personal Information Identity details and contact information Next: Document Upload
Document Upload Upload required supporting documents Next: Review & Confirmation
Review & Confirmation Verify information before submission Next: Application Submitted
Application Submitted Confirmation and next steps

Built-in Features

Auto-initialization

Activates when .nds-stepper is on the page. Step states, progress display, and control button handlers attach automatically.

Three Layout Modes

Horizontal, vertical, and radial layouts cover wide forms, narrow sidebars, and compact dashboard widgets respectively.

Automatic State Management

Set data-current and all steps update their completed, current, or upcoming states automatically.

Declarative Control Buttons

Add data-stepper-control to any button to navigate steps without writing JavaScript.

Step Change Events

The nds:stepper:change event fires on every navigation with current step, total, and percentage in the detail.

Responsive Layout

A single stepper adapts across breakpoints via modifier classes like nds-radial-sm and nds-vertical-lg (same pattern as nds-tableView-sm). One DOM tree renders as horizontal, vertical, or radial depending on viewport.

Look-Ahead Preview

Add .nds-stepper-next inside any step to show the upcoming step name. Automatically hidden on horizontal and vertical layouts; surfaces only in radial.

Programmatic Control

Navigate with NDS.Stepper.next(id), NDS.Stepper.previous(id), and NDS.Stepper.goTo(id, step).

Usage Guidelines

Best Practices

  • Use steppers for multi-step forms like registration, applications, and onboarding flows where the user completes discrete stages in order
  • Use the horizontal layout when you have enough width and want all steps visible at once. This is the default and works best with 3 to 5 steps
  • Use the vertical layout when steps need detailed content, action buttons, or the interface is narrow (sidebars, mobile drawers). Add nds-reverse to flip progress direction from bottom-to-top, useful for timelines or chat-like flows
  • Use the radial layout for compact spaces like dashboard cards or mobile headers where only the current step needs to be visible
  • Use the responsive modifier classes (nds-{horizontal|vertical|radial}-{sm|md|lg}) when one flow spans multiple breakpoints. Same convention as nds-tableView-sm. The single DOM tree carrying the combined radial + linear markup morphs via JS; no parallel steppers or manual visibility switching needed
  • Do not use a stepper for indeterminate or percentage-based progress. Use the Progress component instead
  • Do not use a stepper for navigation menus or tab-like interfaces. Use Tabs for switching between independent content panels
  • Use the dot variant when step labels are not needed and visual progress alone is sufficient, such as onboarding slides or image carousels
  • Connecting lines between steps are shown by default on all steps except the last
  • Keep step titles short (2 to 4 words). Use the description for additional context
  • In radial steppers, add .nds-stepper-next inside the step text to preview the upcoming step name. Omit it on the final step
  • Radial steppers work best with 3 to 6 steps. Fewer than 3 makes the circle progress hard to read; more than 6 makes step titles too compressed
  • Always provide a unique id on the stepper container so control buttons and the JS API can target it

Modifier Classes

ClassApplies toDescription
nds-verticalContainerSwitches to top-to-bottom layout with vertical connecting lines
nds-radialContainerCircular progress indicator showing one step at a time
nds-dotContainerReplaces numbered circles with 16px dots (horizontal and vertical)
nds-smContainerSmaller radial circle (48px, radial only)
nds-lgContainerLarger circle size (40px linear, 96px radial)
nds-xlContainerExtra-large circle size (48px linear, 120px radial)
nds-centerContainerCenters step content beneath each circle (horizontal only)
nds-oncolorContainerAdapts colors for dark or branded backgrounds
nds-reverseContainerReverses vertical stepper direction so progress flows bottom-to-top (vertical only)
nds-neutralContainerNeutral gray progress circle color (radial only)
nds-horizontal-sm / -md / -lgContainerForces horizontal layout on mobile / tablet / desktop respectively. Combine with other breakpoint-scoped variants to compose a responsive layout
nds-vertical-sm / -md / -lgContainerForces vertical layout on mobile / tablet / desktop respectively
nds-radial-sm / -md / -lgContainerForces radial layout on mobile / tablet / desktop respectively. Example: nds-radial-sm nds-vertical-lg = radial on mobile, horizontal on tablet, vertical on desktop

Data Attributes

AttributeDescription
data-currentSet on the .nds-stepper container. The active step number (starting from 1). Updating this attribute triggers an automatic UI refresh.
data-totalSet on the .nds-stepper container. Total number of steps. Updated automatically on init but can be set manually.
data-step-textSet on .nds-stepper-circle. Overrides the auto-generated step number with custom text.
data-stepper-controlSet on any button. Values: next, previous, or goto. Buttons inside a stepper target their parent automatically.
data-stepper-targetSet on control buttons outside a stepper. The ID of the stepper to control.
data-stepper-valueSet on goto control buttons. The step number to navigate to.
data-state="completed"Set on .nds-stepper-step. Marks the step as completed with a checkmark icon. Managed automatically by JS.
data-state="current"Set on .nds-stepper-step. Marks the step as the active step. Managed automatically by JS.
data-state="upcoming"Set on .nds-stepper-step. Marks the step as a future step with muted styling. Managed automatically by JS.

CSS Custom Properties

PropertyDefaultDescription
--stepper-size32pxCircle diameter for linear steppers. Overridden by size classes
--stepper-gaptoken-basedSpacing between steps. Adjusts automatically with size classes
--progress-sizevar(--stepper-size)Circle diameter for radial steppers. Inherits from --stepper-size, which radial size classes override

JavaScript API

Steppers auto-initialize on page load. Access instances via NDS.Stepper.get(id) or call convenience methods directly. The nds:stepper:change event fires on every step change.

// ── Global convenience methods ────────────────────── NDS.Stepper.next('my-stepper'); // Advance to next step NDS.Stepper.previous('my-stepper'); // Go back one step NDS.Stepper.goTo('my-stepper', 3); // Jump to step 3 // ── Instance methods ──────────────────────────────── const stepper = NDS.Stepper.get('my-stepper'); stepper.next(); // Advance (marks last step completed on linear steppers) stepper.previous(); // Go back (un-completes last step if completed) stepper.goTo(2); // Jump to specific step stepper.destroy(); // Disconnect observer and clean up // ── Instance properties ───────────────────────────── stepper.current; // Current step number stepper.total; // Total number of steps stepper.progress; // Completion percentage (0 to 100) // ── Listen for step changes ───────────────────────── document.addEventListener('nds:stepper:change', (e) => { e.detail.currentStep; // Active step number e.detail.totalSteps; // Total steps e.detail.progressPercentage; // Completion percentage }); // ── Data attribute control (alternative) ──────────── // Updating data attributes triggers automatic UI refresh const el = document.getElementById('my-stepper'); el.dataset.current = '2'; // Moves to step 2 el.dataset.total = '5'; // Updates total steps // ── Re-initialize after dynamic HTML ──────────────── NDS.Stepper.init();
Was this page useful?
60% of users said Yes from 2843 Feedbacks