ShellUI Logo
ShellUI

Stepper

Multi-step wizard with a new compositional StepperList, StepperStep, and StepperContent API.

v0.3.0-alpha.2 overhauled the Stepper. @bind-CurrentStep is now @bind-Value, and a new compositional mode lets you place step headers and content manually. The old data-driven StepItems mode still works.

What changed from v0.2.x

v0.2.1v0.3.0-alpha.2
@bind-CurrentStep@bind-Value
Data-driven onlyData-driven or compositional mode
No sub-componentsStepperList, StepperStep, StepperContent

Known issue

Active-state highlighting may not always reflect the current step in some edge cases. This is a known issue shipped as-is in v0.3.0-alpha.2.

Installation

shellui add stepper

stepper-list, stepper-step, and stepper-content are auto-installed as dependencies.

Usage

<Stepper @bind-Value="_step">
    <StepperList>
        <StepperStep Step="0" Title="Account" Description="Create your account" />
        <StepperStep Step="1" Title="Profile" Description="Set up your profile" />
        <StepperStep Step="2" Title="Review" Description="Review and submit" />
    </StepperList>

    <StepperContent Step="0">
        <div class="space-y-3 mt-6">
            <Input Placeholder="Email" />
            <Input Type="password" Placeholder="Password" />
        </div>
    </StepperContent>

    <StepperContent Step="1">
        <div class="space-y-3 mt-6">
            <Input Placeholder="Full Name" />
            <Textarea Placeholder="Bio" />
        </div>
    </StepperContent>

    <StepperContent Step="2">
        <div class="mt-6 rounded-md border p-4 text-sm">
            <p>Review your information and click Finish.</p>
        </div>
    </StepperContent>
</Stepper>

@code {
    private int _step = 0;
}

Data-driven mode (still works)

<Stepper StepItems="@_steps" @bind-Value="_step" />

@code {
    private int _step = 0;

    private List<StepItem> _steps = new()
    {
        new()
        {
            Title = "Account",
            Description = "Set up your account",
            Content = @<div><Input Placeholder="Email" /></div>
        },
        new()
        {
            Title = "Profile",
            Description = "Complete your profile",
            Content = @<div><Input Placeholder="Full Name" /></div>
        },
        new()
        {
            Title = "Done",
            Content = @<p>All set!</p>
        }
    };
}

Stepper inside a Dialog

<Dialog>
    <DialogTrigger>Start wizard</DialogTrigger>
    <DialogContent>
        <DialogHeader>
            <DialogTitle>Setup wizard</DialogTitle>
        </DialogHeader>
        <Stepper @bind-Value="_step">
            <StepperList>
                <StepperStep Step="0" Title="Step 1" />
                <StepperStep Step="1" Title="Step 2" />
            </StepperList>
            <StepperContent Step="0"><p>Step 1 content</p></StepperContent>
            <StepperContent Step="1"><p>Step 2 content</p></StepperContent>
        </Stepper>
    </DialogContent>
</Dialog>

@code { private int _step = 0; }

API Reference

<Stepper>

ParameterTypeDefaultDescription
Valueint0Active step index (use @bind-Value)
ValueChangedEventCallback<int>Fired on step change
StepItemsList<StepItem>?nullData-driven mode items
Classstring?nullAdditional CSS classes
ChildContentRenderFragment?nullCompositional mode content

<StepperList>

ParameterTypeDefaultDescription
ChildContentRenderFragmentStepperStep headers

<StepperStep>

ParameterTypeDefaultDescription
StepintZero-based step index
TitlestringStep label
Descriptionstring?nullSecondary label

<StepperContent>

ParameterTypeDefaultDescription
StepintShown when parent Stepper.Value matches
ChildContentRenderFragmentStep panel content

On this page