const ProgressStepsExample = () => {return (<ProgressSteps><ProgressStepComplete as="button" onClick={() => {}}>Sign up</ProgressStepComplete><ProgressStepError as="button" onClick={() => {}}>Validate email</ProgressStepError><ProgressStepCurrent as="button" onClick={() => {}}>Complete profile</ProgressStepCurrent><ProgressStepIncomplete as="button" onClick={() => {}}>Add friends</ProgressStepIncomplete><ProgressStepIncomplete as="button" onClick={() => {}} disabled>Start event</ProgressStepIncomplete></ProgressSteps>);};render(<ProgressStepsExample />);
Progress Steps are a visual representation of a complex task broken up into multiple steps, ideally 3–5. They indicate what has and what needs to be done to fully complete the task. Use Progress Steps to show a clear path to completion, especially when the task is nonlinear or can’t be completed in one sitting.
Not all multi-step tasks need Progress Steps. Tasks that are short, straightforward, and linear probably don’t need the extra layer of information that Progress Steps provides.
Each step can communicate one of these statuses:
- Complete: The user has completed this step with no more action needed.
- Incomplete: The user has interacted with this step but there is still more action needed.
- Current: The user is currently on this step.
- Error: The user has interacted with this step but more action is required that will prevent completing the full task.
- Incomplete + Disabled: This step is not yet reached by a user.
Progress Steps
- Progress Steps show users an outline of a complex multi-step task across multiple pages or apps.
- Progress Steps convey progression and have interactive status states.
Ordered Display List
Ordered Display Lists structure tasks but don’t show progression or status through a multi-step task.
Timeline
- Timeline displays the history or sequence of events, focusing on what has happened over time.
- Use Timeline when user interaction is secondary, and progress does not depend on user actions since the process continues even without direct user input.
- Give each step a concise label describing what the goal of that step is.
- Each step icon has a
title
prop whose value is the current status of that step (e.g. complete, incomplete, etc.) to inform screen readers of a step's status. This label is adjustable for internationalization. - The ProgressStep has
role=list
and each step hasrole=listitem
for screen readers. - The ProgressStep has
aria-current
set tostep
for the current step.
Use Progress Steps as buttons when each step triggers an in-page action and doesn’t have a unique URL. We recommend using this button action to save information in each step.
Only button steps may be disabled.
const ProgressStepsExample = () => {return (<ProgressSteps><ProgressStepComplete as="button" onClick={() => {}}>Sign up</ProgressStepComplete><ProgressStepError as="button" onClick={() => {}}>Validate email</ProgressStepError><ProgressStepCurrent as="button" onClick={() => {}}>Complete profile</ProgressStepCurrent><ProgressStepIncomplete as="button" onClick={() => {}}>Add friends</ProgressStepIncomplete><ProgressStepIncomplete as="button" onClick={() => {}} disabled>Start event</ProgressStepIncomplete></ProgressSteps>);};render(<ProgressStepsExample />);
Use Progress Steps as anchors when each step links to other pages and has a unique URL.
const ProgressStepsExample = () => {return (<ProgressSteps><ProgressStepComplete as="a" href="#">Sign up</ProgressStepComplete><ProgressStepError as="a" href="#">Validate email</ProgressStepError><ProgressStepCurrent as="a" href="#">Complete profile</ProgressStepCurrent><ProgressStepIncomplete as="a" href="#">Add friends</ProgressStepIncomplete></ProgressSteps>);};render(<ProgressStepsExample />);
Use Progress Steps as divs when steps have no need for user interaction.
const ProgressStepsExample = () => {return (<ProgressSteps><ProgressStepComplete as="div">Sign up</ProgressStepComplete><ProgressStepError as="div">Validate email</ProgressStepError><ProgressStepCurrent as="div">Complete profile</ProgressStepCurrent><ProgressStepIncomplete as="div">Add friends</ProgressStepIncomplete></ProgressSteps>);};render(<ProgressStepsExample />);
You can use vertical Progress Steps when the content of the task is tall and narrow, or you need to add additional content to each step.
const ProgressStepsExample = () => {return (<ProgressSteps orientation="vertical"><ProgressStepComplete as="div">Sign up</ProgressStepComplete><ProgressStepError as="div">Validate email</ProgressStepError><ProgressStepCurrent as="div">Complete profile</ProgressStepCurrent><ProgressStepIncomplete as="div">Add friends</ProgressStepIncomplete></ProgressSteps>);};render(<ProgressStepsExample />);
Use ProgressStepContent
to add additional content to non-interactive vertical Progress Steps.
Use this when each step requires minimal content or actions, like opening a modal, redirecting, or entering text, and users need to complete steps in a specific sequence, with progress tracked throughout the entire task.
Steps that are completed in other pages and have unique URLs do not automatically track status.
Implement the logic locally to ensure the step's status is accurately reflected within the Progress Steps component.
const ProgressStepsExample = () => {return (<ProgressSteps orientation="vertical"><ProgressStepComplete as="div">Data warehouse connected<ProgressStepContent><Box paddingX="space10" paddingY="space30"><Box display="flex" columnGap="space50" paddingY="space40"><Avatar size="sizeIcon90" name="Twilio Paste" variant="entity" icon={BusinessIcon} /><Box><Heading variant="heading50">Snowflake</Heading><Box display="flex" flexDirection="column"><Paragraph>Account: accountname</Paragraph><Paragraph>Database: snowflakedatabasename</Paragraph><Paragraph>Warehouse: snowflakewarehousename</Paragraph><Paragraph>User: bsmith</Paragraph><Paragraph marginBottom="space0">Password: *****</Paragraph></Box><Box marginTop="space80"><ButtonGroup><Button variant="secondary">Edit</Button><Button variant="destructive_secondary">Remove</Button></ButtonGroup></Box></Box></Box></Box></ProgressStepContent></ProgressStepComplete><ProgressStepCurrent as="div">Create a model<ProgressStepContent><Box paddingX="space10" paddingY="space30"><Paragraph marginBottom="space0">Models are SQL queries that define sets of data to sync using Reverse ETL.</Paragraph><Box marginTop="space50"><Button variant="primary">Define model</Button></Box></Box></ProgressStepContent></ProgressStepCurrent><ProgressStepIncomplete as="div">Create mapping<ProgressStepContent><Box paddingX="space10" paddingY="space30"><Paragraph marginBottom="space0">Mappings determine how data extracted from your warehouse is mapped to fields in Flex</Paragraph><Box marginTop="space50"><Button variant="primary" disabled>Continue mapping</Button></Box></Box></ProgressStepContent></ProgressStepIncomplete></ProgressSteps>);};render(<ProgressStepsExample />);
Each step within the Progress Steps component has a label which can be set to adjust the icon's title for internationalization.
const ProgressStepsExample = () => {return (<ProgressSteps><ProgressStepComplete i18nCompleteLabel="Complété" as="div">S'inscrire</ProgressStepComplete><ProgressStepError i18nErrorLabel="Erreur" as="div">Email validé</ProgressStepError><ProgressStepCurrent i18nCurrentLabel="Actuelle" as="div">Complétez votre profil</ProgressStepCurrent><ProgressStepIncomplete i18nIncompleteLabel="Incomplet" as="div">Ajouter des amis</ProgressStepIncomplete></ProgressSteps>);};render(<ProgressStepsExample />);
- Each step must have a label. Keep the label concise with fewer than 5 words per label.
- Skip articles like “a” or “the” to shorten the step.
- Generally, start each step with a verb to keep the user grounded in the task at hand.
- If the process has 5 steps and describing each one with a verb + noun is too long, consider shortening the step labels to just a verb, and using the in-page step label to clarify the full scope of the task. For example, use “Add” as a step label, but include “Add entry step” as the page label.
- If the process does not fit into a mental model of performing tasks, make sure each step is phrased consistently. For example, “Business profile” and “Brand registration.”
- Keep the placement of Progress Steps consistent between different pages (steps).
ProgressStepSeparator is no longer required starting v2.2.1. The separator is now automatically added between each step using CSS. It is backwards compatible, so previous versions will still work.
Show the error status on a step when it’s not the current step they’re on. When a
user navigates to the step that has errors, use ProgressStepCurrent
to set the status of the step to current,
and use in-page validation to then communicate the errors in the current page.
Check out the Error state pattern for more guidance.
Do
Use Progress Steps for complex tasks with 3–5 steps that can't be completed in one session.
Don't
Don’t use Progress Steps for every single kind of task that has multiple steps. A line of text can be used as an alternative to show progression (e.g., “Step 1 of 2”)
Do
Make the labels of each step short, descriptive, and consistent. Use fewer than 5 words for each step label.
Don't
Don’t use long or inconsistent labels with mismatched parts of speech.
Do
Keep Progress Steps in a consistent location between steps or pages.
Don't
Don’t change the placement of Progress Steps between steps or pages.
Do
Include only one Progress Steps component per task or page.
Don't
Don’t embed a Progress Steps component within a task that’s already being tracked with another Progress Steps component. Don’t use multiple Progress Steps per page.