Stepper
The Stepper component is a sequential step-by-step navigation interface that offers a structured, user-friendly way to guide users through a series of steps in a process. It ensures clarity and ease of use with visual progress indicators and interactive controls, helping users understand their progress and navigate each step effortlessly.
Step 1
Additional Examples
Change Orientation
We can pass the orientation
prop to the Stepper component to change the orientation from "vertical" to "horizontal".
With Descriptions
Step 1
We can add optional description text to provide additional context.
Make Steps Optional
Step 1
If you want to make a step optional, you can add optional: true
in the array of steps.
In this example, the second step is optional. You can visualize the change of the label in the Next
button
Legend Variants
circle
: allows you to display each step as a circular shape. The label and description are positioned horizontally next to the button of each step.circle-alt
: same circular design as the circle variant but the label and description are positioned vertically below the button of each step and applies a centered effect.line
: this variant enables a modern line design with titles and descriptions positioned below the line.
Step 1
Label Sizes
Step 1
Steps can be set to one of 3 sizes: sm
, md
, and lg
which can be set using the size
prop.
Mobile Breakpoints (Responsive behavior)
By using the orientation prop you are able to switch between horizontal (default) and vertical orientations. By default, when in mobile view the Steps component will switch to vertical orientation. You can also customize the mobile breakpoint behavior by using the mobileBreakpoint
prop.
Status Feedback
Step 1
When communicating with a user, colors, and visuals can play a considerable part; by using color as feedback, we can effectively communicate status messages to users without overcomplicating with words. We can use the state
prop to display a loading or error indicator with the values of loading | error
.
This prop can be used globally within the Stepper component or locally in the Step component affected by this state.
Custom Icons
Step 1
If you want to use custom icons instead of the default numerical indicators, you can do so by using the icon
prop on the Step component.
To change the general check and error icons, we can use the checkIcon
and
errorIcon
prop inside the Stepper component
Clickable Step Indicators
Step 1
If you need the step indicator to be clickable and to be able to set a custom logic for the onClick event, we can use the onClickStep
prop in the Stepper
component globally or in Step
locally.
In this example we have placed a global alert when any step is clicked. Try clicking on any step to see the result.
The onClickStep
function takes two parameters: the index of the clicked step and a setter function that changes the current step to the clicked step. This setter is especially useful for sending an onClick event globally when the useStepper
hook is not accessible.
Step Footer
When using the vertical orientation, we may want to have the footer buttons inside each step and not located at the end. To achieve this, we can simply move our footer below all the steps inside the Stepper component.
Automatic Scrolling
To enable automatic scrolling as a user progresses through steps use the scrollTracking
prop on the Stepper component.
With Forms
To use Form
components within the Stepper
component, use the useStepper
hook to control the component.
This example uses the Form
component and the react-hook-form
hooks to create a form with ZOD validations.
You can also use the component with server actions.
Custom Styling
Step 1
In this example we will change the style of the steps and the separator. In addition, we will also change the variables that define the size and gap of the icon for each step.
...
<Stepper
initialStep={0}
steps={steps}
styles={{
"step-button-container": cn(
"text-purple-700 rounded-none",
"data-[current=true]:border-purple-500 data-[current=true]:bg-purple-50",
"data-[active=true]:bg-purple-500 data-[active=true]:border-purple-500"
),
"horizontal-step":
"data-[completed=true]:[&:not(:last-child)]:after:bg-purple-500",
}}
variables={{
"--step-icon-size": "60px",
"--step-gap": "20px",
}}
>
// Rest of the code
</Stepper>
...
To customize the styles of the Steps component, Stepper
provides a set of CSS variables for each part of the component. You can use these variables to override default styles:
main-container
: The main container of the stepper.horizontal-step
: Outer wrapper for each step in horizontal layouthorizontal-step-container
: Inner wrapper for each step in horizontal layoutvertical-step
: Outer wrapper for each step in vertical layoutvertical-step-container
: Inner wrapper for each step in vertical layoutvertical-step-content
: Content wrapper for each step in vertical layoutstep-button-container
: Wrapper for the step buttonstep-label-container
: Wrapper for the label and descriptionstep-label
: The label of the stepstep-description
: The description of the step
State specific variables:
data-active
: The active stepdata-invalid
: The step with an errordata-loading
: The step in loading statedata-clickable
: The step that is clickabledata-completed
: The step that is completeddata-optional
: The step that is optional
Sure, here's the rephrased version:
Finally, the variables
prop lets you define values for the CSS variables used to position the separator lines. This is particularly useful when custom elements of varying sizes need to be set beyond the default options provided by the component:
--step-icon-size
: defines the width of the step icon. It is important to define this value in pixels. By default it has the values of the width of a button depending if the style is default (36px, 40px, 44px
).--step-gap
: defines the gap between the separator and the elements that follow it. The default value is8px
.
Configurable Props
<Stepper>
Prop | Type | Default/ Options | Description |
---|---|---|---|
initialStep | number | Currently active step | |
steps | StepItem[] | An array of objects with the label and description of each step. | |
orientation | "horizontal" | "vertical" | "horizontal" | The orientation of the stepper. |
size | "sm" | "md" | "lg" | "md" | The size of the stepper. |
state | "loading" | "error" | The state of the stepper (global). | |
icon | object | The custom icon to be displayed in the step button. | |
checkIcon | object | The custom icon to be displayed when the step is completed. | |
errorIcon | object | The custom icon to be displayed when the step has an error. | |
responsive | boolean | true | If the stepper should be responsive. |
mobileBreakpoint | number | 768px | The breakpoint at which the stepper switches to vertical orientation. |
scrollTracking | boolean | false | Scroll to the active step when scrolling forward or backward. |
styles |
| Custom styles for the stepper. | |
variables |
| Custom css variables values for the stepper. | |
onClickStep | (index: number, setStep: (index: number) => void) => void | The function to be executed when a step is clicked. | |
variant | "circle" | "circle-alt" | "line" | "circle" | The design variant of the stepper. |
expandVerticalSteps | boolean | false | Control whether or not the vertical steps should collapse. |
<Step>
Prop | Type | Default/ Options | Description |
---|---|---|---|
id | string | The id of the step. | |
label | string | The label of the step. | |
description | string | The description of the step. | |
optional | boolean | If the step is optional. | |
icon | object | The custom icon to be displayed in the step button. | |
state | "loading" | "error" | The state of the step (local). | |
isCompletedStep | boolean | Individually control each step state, defaults to active step. | |
isKeepError | boolean | Individually control if each step should keep showing the error state. | |
checkIcon | object | The custom icon to be displayed when the step is completed. | |
errorIcon | object | The custom icon to be displayed when the step has an error. | |
onClickStep | (index: number, setStep: (index: number) => void) => void | The function to be executed when a step is clicked. |
useStepper
In order to use the hook, we simply have to import it and use it inside the <Stepper />
component as a wrapper.
import { useStepper } from "@/components/ui/stepper"
export funcion UseStepperDemo() {
{ ... } = useStepper();
return (
<div>
{ ... }
</div>
)
}
The hook returns the following values:
Prop | Type | Default/ Options | Description |
---|---|---|---|
activeStep | number | The current active step. | |
isLastStep | boolean | If the current step is the last step. | |
isOptionalStep | boolean | If the current step is optional. | |
isDisabledStep | boolean | If the current step is disabled. | |
isError | boolean | If the stepper has an error. | |
isLoading | boolean | If the stepper is loading. | |
isVertical | boolean | If the stepper is vertical. | |
expandVerticalSteps | boolean | If the vertical steps should be expanded. | |
nextStep | () => void | Function to go to the next step. | |
prevStep | () => void | Function to go to the previous step. | |
setStep | (index: number) => void | Function to set a specific step. | |
resetSteps | () => void | Function to reset the stepper. | |
stepCount | number | The total number of steps. | |
initialStep | number | The initial active step. | |
clickable | boolean | If the steps are clickable. | |
hasCompletedAllSteps | boolean | If all steps have been completed. | |
currentStep | StepItem | The current step object. |