Stepper
The Stepper component guides multi-step flows with compound parts, keyboard navigation, and semantic progress states.
Usage
Compose the flow with Stepper.Root, Stepper.List, Stepper.Item, Stepper.Indicator, Stepper.Title, Stepper.Description, and Stepper.Separator.
Account Create your login credentials.
Step 1 of 4. Completed step. 2 Shipping Confirm your delivery address.
Step 2 of 4. Current step. 3 Payment Choose your payment method.
Step 3 of 4. Pending step. 4 Review Review and place the order.
Step 4 of 4. Pending step. import React from 'react' ;
import { Stepper } from '@nathan3boss/ui/stepper' ;
import { ExampleFrame } from '@docs-support/example-frame' ;
const steps = [
{
description : 'Create your login credentials.' ,
title : 'Account' ,
value : 'account' ,
} ,
{
description : 'Confirm your delivery address.' ,
title : 'Shipping' ,
value : 'shipping' ,
} ,
{
description : 'Choose your payment method.' ,
title : 'Payment' ,
value : 'payment' ,
} ,
{
description : 'Review and place the order.' ,
title : 'Review' ,
value : 'review' ,
} ,
];
export default () => {
return (
< ExampleFrame maxWidth = "880px" width = "100%" >
< Stepper.Root ariaLabel = "Checkout progress" defaultValue = "shipping" >
< Stepper.List >
{ steps .map ((step , index) => (
< Stepper.Item key = { step .value} value = { step .value}>
< Stepper.Indicator />
< Stepper.Title >{ step .title}</ Stepper.Title >
< Stepper.Description >{ step .description}</ Stepper.Description >
{index < steps . length - 1 ? < Stepper.Separator /> : null }
</ Stepper.Item >
))}
</ Stepper.List >
</ Stepper.Root >
</ ExampleFrame >
);
};
Vertical Layout
Use orientation="vertical" for onboarding flows, setup checklists, or sidebars where the content benefits from more reading space.
Workspace Name and personalize the space.
Step 1 of 3. Completed step. 2 Members Invite your team and set roles.
Step 2 of 3. Current step. 3 Review Check the settings before launch.
Step 3 of 3. Pending step. import React from 'react' ;
import { Stepper } from '@nathan3boss/ui/stepper' ;
import { ExampleFrame } from '@docs-support/example-frame' ;
export default () => {
return (
< ExampleFrame width = "360px" >
< Stepper.Root
ariaLabel = "Workspace setup"
defaultValue = "members"
orientation = "vertical"
variant = "compact"
>
< Stepper.List >
< Stepper.Item value = "workspace" >
< Stepper.Indicator />
< Stepper.Title >Workspace</ Stepper.Title >
< Stepper.Description >Name and personalize the space.</ Stepper.Description >
< Stepper.Separator />
</ Stepper.Item >
< Stepper.Item value = "members" >
< Stepper.Indicator />
< Stepper.Title >Members</ Stepper.Title >
< Stepper.Description >Invite your team and set roles.</ Stepper.Description >
< Stepper.Separator />
</ Stepper.Item >
< Stepper.Item value = "review" >
< Stepper.Indicator />
< Stepper.Title >Review</ Stepper.Title >
< Stepper.Description >Check the settings before launch.</ Stepper.Description >
</ Stepper.Item >
</ Stepper.List >
</ Stepper.Root >
</ ExampleFrame >
);
};
Controlled Flow
Use the controlled API when the active step depends on external form state, async validation, or navigation buttons.
Account Create your login credentials.
Step 1 of 4. Completed step. 2 Shipping Confirm your delivery address.
Step 2 of 4. Current step. 3 Payment Choose your payment method.
Step 3 of 4. Pending step. 4 Review Review and place the order.
Step 4 of 4. Pending step. Back Next step
import React , { useState } from 'react' ;
import { Button } from '@nathan3boss/ui/button' ;
import { Stepper } from '@nathan3boss/ui/stepper' ;
import { ExampleFrame } from '@docs-support/example-frame' ;
const steps = [
{
description : 'Create your login credentials.' ,
title : 'Account' ,
value : 'account' ,
} ,
{
description : 'Confirm your delivery address.' ,
title : 'Shipping' ,
value : 'shipping' ,
} ,
{
description : 'Choose your payment method.' ,
title : 'Payment' ,
value : 'payment' ,
} ,
{
description : 'Review and place the order.' ,
title : 'Review' ,
value : 'review' ,
} ,
];
export default () => {
const [ value , setValue ] = useState ( 'shipping' );
const currentIndex = steps .findIndex ((step) => step .value === value);
return (
< ExampleFrame gap = "16px" maxWidth = "880px" width = "100%" >
< Stepper.Root ariaLabel = "Checkout progress" onValueChange = {setValue} value = {value}>
< Stepper.List >
{ steps .map ((step , index) => (
< Stepper.Item key = { step .value} value = { step .value}>
< Stepper.Indicator />
< Stepper.Title >{ step .title}</ Stepper.Title >
< Stepper.Description >{ step .description}</ Stepper.Description >
{index < steps . length - 1 ? < Stepper.Separator /> : null }
</ Stepper.Item >
))}
</ Stepper.List >
</ Stepper.Root >
< div style = {{ display : 'flex' , gap : '12px' }}>
< Button
disabled = {currentIndex === 0 }
onClick = {() => setValue (steps[ Math .max (currentIndex - 1 , 0 )].value)}
variant = "outline"
>
Back
</ Button >
< Button
disabled = {currentIndex === steps . length - 1 }
onClick = {() => setValue (steps[ Math .min (currentIndex + 1 , steps . length - 1 )].value)}
>
Next step
</ Button >
</ div >
</ ExampleFrame >
);
};
States And Accessibility
Use explicit status values for exceptional cases like errors, while the current step and completed history are handled automatically.
Profile Basic account details completed.
Step 1 of 4. Completed step. Verification We still need a valid confirmation code.
Step 2 of 4. Current step. Error state. 3 Delivery Unlocks after verification succeeds.
Step 3 of 4. Disabled step. 4 Review Final confirmation before submission.
Step 4 of 4. Pending step. import React from 'react' ;
import { Stepper } from '@nathan3boss/ui/stepper' ;
import { ExampleFrame } from '@docs-support/example-frame' ;
export default () => {
return (
< ExampleFrame maxWidth = "880px" width = "100%" >
< Stepper.Root ariaLabel = "Registration progress" defaultValue = "verification" >
< Stepper.List >
< Stepper.Item value = "profile" >
< Stepper.Indicator />
< Stepper.Title >Profile</ Stepper.Title >
< Stepper.Description >Basic account details completed.</ Stepper.Description >
< Stepper.Separator />
</ Stepper.Item >
< Stepper.Item status = "error" value = "verification" >
< Stepper.Indicator />
< Stepper.Title >Verification</ Stepper.Title >
< Stepper.Description >We still need a valid confirmation code.</ Stepper.Description >
< Stepper.Separator />
</ Stepper.Item >
< Stepper.Item disabled value = "delivery" >
< Stepper.Indicator />
< Stepper.Title >Delivery</ Stepper.Title >
< Stepper.Description >Unlocks after verification succeeds.</ Stepper.Description >
< Stepper.Separator />
</ Stepper.Item >
< Stepper.Item value = "review" >
< Stepper.Indicator />
< Stepper.Title >Review</ Stepper.Title >
< Stepper.Description >Final confirmation before submission.</ Stepper.Description >
</ Stepper.Item >
</ Stepper.List >
</ Stepper.Root >
</ ExampleFrame >
);
};
The component uses semantic list markup, aria-current="step" for the active item, arrow-key navigation that respects the selected orientation, and Home/End support for longer flows. Screen readers also receive hidden state labels for pending, active, completed, error, and disabled steps.
Best Practices
Keep step titles short and action-oriented.
Use variant="compact" and size="sm" for denser sidebars or narrow containers.
Prefer explicit status="error" only when the user must revisit a step.
Disable later steps when the flow is strictly sequential.
API