Steppers convey progress through numbered steps. It provides a wizard-like workflow.
Steppers display progress through a sequence of logical and numbered steps. They may also be used for navigation. Steppers may display a transient feedback message after a step is saved.
This component is no longer documented in the Material Design guidelines, but MaterialĀ UI will continue to support it.
The Stepper component displays progress through a sequence of logical and numbered steps. It supports horizontal and vertical orientation for desktop and mobile viewports.
Steppers are implemented using a collection of related components:
import Stepper from '@mui/material/Stepper';
import Step from '@mui/material/Step';
import StepLabel from '@mui/material/StepLabel';
Horizontal steppers are ideal when the contents of one step depend on an earlier step.
Avoid using long step names in horizontal steppers.
A linear stepper allows the user to complete the steps in sequence.
The Stepper
can be controlled by passing the current step index (zero-based) as the activeStep
prop. Stepper
orientation is set using the orientation
prop.
This example also shows the use of an optional step by placing the optional
prop on the second Step
component. Note that itās up to you to manage when an optional step is skipped. Once youāve determined this for a particular step you must set completed={false}
to signify that even though the active step index has gone beyond the optional step, itās not actually complete.
{{ādemoā: āHorizontalLinearStepper.jsā}}
Non-linear steppers allow the user to enter a multi-step flow at any point.
This example is similar to the regular horizontal stepper, except steps are no longer automatically set to disabled={true}
based on the activeStep
prop.
The use of the StepButton
here demonstrates clickable step labels, as well as setting the completed
flag. However because steps can be accessed in a non-linear fashion, itās up to your own implementation to
determine when all steps are completed (or even if they need to be completed).
{{ādemoā: āHorizontalNonLinearStepper.jsā}}
Labels can be placed below the step icon by setting the alternativeLabel
prop on the Stepper
component.
{{ādemoā: āHorizontalLinearAlternativeLabelStepper.jsā}}
{{ādemoā: āHorizontalStepperWithError.jsā}}
Here is an example of customizing the component. You can learn more about this in the overrides documentation page.
{{ādemoā: āCustomizedSteppers.jsā}}
Vertical steppers are designed for narrow screen sizes. They are ideal for mobile. All the features of the horizontal stepper can be implemented.
{{ādemoā: āVerticalLinearStepper.jsā}}
The content of a step is unmounted when closed. If you need to make the content available to search engines or render expensive component trees inside your modal while optimizing for interaction responsiveness it might be a good idea to keep the step mounted with:
<StepContent TransitionProps={{ unmountOnExit: false }} />
This component implements a compact stepper suitable for a mobile device. It has more limited functionality than the vertical stepper. See mobile steps for its inspiration.
The mobile stepper supports three variants to display progress through the available steps: text, dots, and progress.
The current step and total number of steps are displayed as text.
import * as React from 'react';
import Box from '@mui/material/Box';
import { useTheme } from '@mui/material/styles';
import MobileStepper from '@mui/material/MobileStepper';
import Paper from '@mui/material/Paper';
import Typography from '@mui/material/Typography';
import Button from '@mui/material/Button';
import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft';
import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight';
const steps = [
{
label: 'Select campaign settings',
description: `For each ad campaign that you create, you can control how much
you're willing to spend on clicks and conversions, which networks
and geographical locations you want your ads to show on, and more.`,
},
{
label: 'Create an ad group',
description:
'An ad group contains one or more ads which target a shared set of keywords.',
},
{
label: 'Create an ad',
description: `Try out different ad text to see what brings in the most customers,
and learn how to enhance your ads using features like ad extensions.
If you run into any problems with your ads, find out how to tell if
they're running and how to resolve approval issues.`,
},
];
export default function TextMobileStepper() {
const theme = useTheme();
const [activeStep, setActiveStep] = React.useState(0);
const maxSteps = steps.length;
const handleNext = () => {
setActiveStep((prevActiveStep) => prevActiveStep + 1);
};
const handleBack = () => {
setActiveStep((prevActiveStep) => prevActiveStep - 1);
};
return (
<Box sx={{ maxWidth: 400, flexGrow: 1 }}>
<Paper
square
elevation={0}
sx={{
display: 'flex',
alignItems: 'center',
height: 50,
pl: 2,
bgcolor: 'background.default',
}}
>
<Typography>{steps[activeStep].label}</Typography>
</Paper>
<Box sx={{ height: 255, maxWidth: 400, width: '100%', p: 2 }}>
{steps[activeStep].description}
</Box>
<MobileStepper
variant="text"
steps={maxSteps}
position="static"
activeStep={activeStep}
nextButton={
<Button
size="small"
onClick={handleNext}
disabled={activeStep === maxSteps - 1}
>
Next
{theme.direction === 'rtl' ? (
<KeyboardArrowLeft />
) : (
<KeyboardArrowRight />
)}
</Button>
}
backButton={
<Button size="small" onClick={handleBack} disabled={activeStep === 0}>
{theme.direction === 'rtl' ? (
<KeyboardArrowRight />
) : (
<KeyboardArrowLeft />
)}
Back
</Button>
}
/>
</Box>
);
}
Use dots when the number of steps is small.
import * as React from 'react';
import { useTheme } from '@mui/material/styles';
import MobileStepper from '@mui/material/MobileStepper';
import Button from '@mui/material/Button';
import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft';
import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight';
export default function DotsMobileStepper() {
const theme = useTheme();
const [activeStep, setActiveStep] = React.useState(0);
const handleNext = () => {
setActiveStep((prevActiveStep) => prevActiveStep + 1);
};
const handleBack = () => {
setActiveStep((prevActiveStep) => prevActiveStep - 1);
};
return (
<MobileStepper
variant="dots"
steps={6}
position="static"
activeStep={activeStep}
sx={{ maxWidth: 400, flexGrow: 1 }}
nextButton={
<Button size="small" onClick={handleNext} disabled={activeStep === 5}>
Next
{theme.direction === 'rtl' ? (
<KeyboardArrowLeft />
) : (
<KeyboardArrowRight />
)}
</Button>
}
backButton={
<Button size="small" onClick={handleBack} disabled={activeStep === 0}>
{theme.direction === 'rtl' ? (
<KeyboardArrowRight />
) : (
<KeyboardArrowLeft />
)}
Back
</Button>
}
/>
);
}
Use a progress bar when there are many steps, or if there are steps that need to be inserted during the process (based on responses to earlier steps).
import * as React from 'react';
import { useTheme } from '@mui/material/styles';
import MobileStepper from '@mui/material/MobileStepper';
import Button from '@mui/material/Button';
import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft';
import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight';
export default function ProgressMobileStepper() {
const theme = useTheme();
const [activeStep, setActiveStep] = React.useState(0);
const handleNext = () => {
setActiveStep((prevActiveStep) => prevActiveStep + 1);
};
const handleBack = () => {
setActiveStep((prevActiveStep) => prevActiveStep - 1);
};
return (
<MobileStepper
variant="progress"
steps={6}
position="static"
activeStep={activeStep}
sx={{ maxWidth: 400, flexGrow: 1 }}
nextButton={
<Button size="small" onClick={handleNext} disabled={activeStep === 5}>
Next
{theme.direction === 'rtl' ? (
<KeyboardArrowLeft />
) : (
<KeyboardArrowRight />
)}
</Button>
}
backButton={
<Button size="small" onClick={handleBack} disabled={activeStep === 0}>
{theme.direction === 'rtl' ? (
<KeyboardArrowRight />
) : (
<KeyboardArrowLeft />
)}
Back
</Button>
}
/>
);
}