Skip to main content
U.S. Flag

An official website of the United States government

CMS Design System

Step List

A step list represents a user's progression through an application or multi-page form. It serves as a table of contents and a way to quickly see where they are and what they should be working on next.

A user interacts with the steps through "Start", "Resume", and "Edit" links.

In the React component, the links' href properties are determined by the step object's href property. One can also optionally pass an onStepLinkClick function that will cancel the default link behavior and call onStepLinkClick with href as a parameter for apps that handle routing with JavaScript.

When a step has substeps and is incomplete, the href property should be set to match the href of the current substep—that is, the first incomplete substep. The "Edit" button will only appear on substeps that have been completed.

<StepList>

The StepList component is the preferred method for building a step list, since it handles all the state logic necessary to produce its markup. A step is represented by an object with text, progress, and routing information and can optionally include an array of substeps as well as a description.

View Source File

Code snippet

Props

React Properties Documentation
NameTypeDefaultDescription
stepsrequiredStepObject[]

An array of step objects that contain text, state, link/button URLs and other info needed to render steps.

componentStepLinkProps['component']

When provided, this will render the passed in component for all link elements. This is useful when integrating with React Router's <Link> or using your own custom component. If more specific control is needed, each step object also accepts a component prop.

showSubSubStepsbooleanfalse

Whether or not to render a substep's substeps.

onStepLinkClickStepLinkProps['onClick']

Function called when a step's Edit, Start, or Resume button/link is clicked. The step's href property will be passed as a parameter.

completedTextstring'Completed'
editTextstring'Edit'
resumeTextstring'Resume'
startTextstring'Start'
actionsLabelTextstring'Primary actions for %{step}'

A template string for the aria-label describing a step's actions where the substring %{step} is replaced with that step's heading.

descriptionLabelTextstring'Description for %{step}'

A template string for the aria-label for a step's description where the substring %{step} is replaced with that step's heading.

substepsLabelTextstring'Secondary actions for %{step}'

A template string for the aria-label describing a step's substeps where the substring %{step} is replaced with that step's heading.

<Step>

Step Object

NameTypeDescription
completedboolWhether the step has been completed
componentelement, funcWhen provided, this will render the passed in component for link elements in this Step. This is useful when integrating with React Router's <Link> or using your own custom component.
descriptionstringAdditional text to dsiplay under (only rendered for top-level steps)
heading RequiredstringText to display as the step heading
headingLevel'1', '2', '3', '4', '5'Heading type to override default <h2>.
href RequiredstringURL or partial URL that routes to the step. Will be passed to onStepLinkClick as first parameter
idstringUnique string representing the step. WIll be passed to onStepLinkClick as second parameter
isNextStepboolWhether this is the next unstarted step
linkTextstringAlternative text for the link or button for this step. Will override the defaults
onClickfunconClick handler for this specific step's link/button
startedboolWhether the step has been started
stepsStepObject[]Array of substeps

Guidance

Managing list state

Substeps

The <StepList> component takes an array of step objects. From there steps can be broken down infinitely into sub-steps. This allows us to have unique URLs for each part of a step; however, by default we only display two levels of this tree —the step and substep. This default behavior should remain unchanged except for special circumstances. It is better not to overwhelm the user with showing all the substeps and giving them names.

We do, nonetheless, encourage the use of sub-substeps that are not visible where these substeps span multiple pages and have their own unique URLs. If, for example, the user completes the first page of the household > overall substep where they list the household members but has not completed the second page where they define those members' relationships to each other, we want the "Resume" button to take them back to the relationships page and not the first page where they entered their names. This, of course, requires an extra steps-building process to update a top-level steps' href property by traversing the substep tree to find the first incomplete step. See the Completed, started, and isNextStep section below for an example JavaScript function that can change the href of steps based on their substeps.

Completed, started, and isNextStep

The state of a step object will be defined for these purposes as the values of its completed, started, and isNextStep properties. These correspond to different visual states when rendered by the <StepList>, showing "Completed", "Resume", or "Start" respectively. For steps with substeps, the state should be representative of the collective states of its substeps. For example, if a step has substeps that have completed: false, that step should not have completed: true because not all of its substeps have been completed. Similarly a step can only be started if at least one of its substeps has been started. This should be true for each of the substep's substeps and so on. Below is an example function that can propagate this state information up from the smallest substep to the largest step before passing the steps array to the <StepList> component.

function propagateSubstepState(step) {
  if (step.steps) {
    const steps = step.steps.map(propagateSubstepState);
    const newStep = {
      ...step,
      steps,
      started: steps.some((s) => s.started),
      completed: steps.every((s) => s.completed),
    };
    if (!newStep.completed) {
      const nextStep = steps.find((s) => !s.completed);
      newStep.href = nextStep.href;
    }
    return newStep;
  } else {
    return step;
  }
}

// ...
//
// Render function:

const steps = rawSteps.map(propagateSubstepState);
return <StepList steps={steps} />;

Customization

The following Sass variables can be overridden to customize StepList patterns:

VariableDefault Core Theme Value
$steplist__color$color-gray
$steplist__color--current$color-primary
$steplist__background-color--current$color-primary
$steplist-step__color$color-gray
$steplist-step__border-color$color-border
$steplist-step__border-color--default$color-gray
$steplist-step__color--current$color-white
$steplist-step__color--completed$color-base
$steplist-step__background-color--completed$color-base