The Stepper component displays a wizard-like workflow by guiding users through the multi-step progression.
import { StepperModule } from 'primeng/stepper';
Stepper consists of a combination of StepList, Step, StepPanels and StepPanel components. The value property is essential for associating Step and StepPanel with each other.
<p-stepper [value]="1" class="basis-[50rem]">
<p-step-list>
<p-step [value]="1">Header I</p-step>
<p-step [value]="2">Header II</p-step>
<p-step [value]="3">Header II</p-step>
</p-step-list>
<p-step-panels>
<p-step-panel [value]="1">
<ng-template #content let-activateCallback="activateCallback">
<div class="flex flex-col h-48">
<div
class="border-2 border-dashed border-surface-200 dark:border-surface-700 rounded bg-surface-50 dark:bg-surface-950 flex-auto flex justify-center items-center font-medium"
>
Content I
</div>
<div class="flex pt-6 justify-end">
<p-button label="Next" icon="pi pi-arrow-right" iconPos="right" (onClick)="activateCallback(2)" />
</div>
</div>
</ng-template>
</p-step-panel>
<p-step-panel [value]="2">
<ng-template #content let-activateCallback="activateCallback">
<div class="flex flex-col h-48">
<div
class="border-2 border-dashed border-surface-200 dark:border-surface-700 rounded bg-surface-50 dark:bg-surface-950 flex-auto flex justify-center items-center font-medium"
>
Content II
</div>
</div>
<div class="flex pt-6 justify-between">
<p-button label="Back" severity="secondary" icon="pi pi-arrow-left" (onClick)="activateCallback(1)" />
<p-button label="Next" icon="pi pi-arrow-right" iconPos="right" (onClick)="activateCallback(3)" />
</div>
</ng-template>
</p-step-panel>
<p-step-panel [value]="3">
<ng-template #content let-activateCallback="activateCallback">
<div class="flex flex-col h-48">
<div
class="border-2 border-dashed border-surface-200 dark:border-surface-700 rounded bg-surface-50 dark:bg-surface-950 flex-auto flex justify-center items-center font-medium"
>
Content III
</div>
</div>
<div class="flex pt-6 justify-start">
<p-button label="Back" icon="pi pi-arrow-left" iconPos="right" (onClick)="activateCallback(2)" />
</div>
</ng-template>
</p-step-panel>
</p-step-panels>
</p-stepper>
Vertical layout requires StepItem as a wrapper of Step and StepPanel components.
<p-stepper [value]="1">
<p-step-item [value]="1">
<p-step>Header I</p-step>
<p-step-panel>
<ng-template #content let-activateCallback="activateCallback">
<div class="flex flex-col h-48">
<div
class="border-2 border-dashed border-surface-200 dark:border-surface-700 rounded bg-surface-50 dark:bg-surface-950 flex-auto flex justify-center items-center font-medium"
>
Content I
</div>
</div>
<div class="py-6">
<p-button label="Next" (onClick)="activateCallback(2)" />
</div>
</ng-template>
</p-step-panel>
</p-step-item>
<p-step-item [value]="2">
<p-step>Header II</p-step>
<p-step-panel>
<ng-template #content let-activateCallback="activateCallback">
<div class="flex flex-col h-48">
<div
class="border-2 border-dashed border-surface-200 dark:border-surface-700 rounded bg-surface-50 dark:bg-surface-950 flex-auto flex justify-center items-center font-medium"
>
Content II
</div>
</div>
<div class="flex py-6 gap-2">
<p-button label="Back" severity="secondary" (onClick)="activateCallback(1)" />
<p-button label="Next" (onClick)="activateCallback(3)" />
</div>
</ng-template>
</p-step-panel>
</p-step-item>
<p-step-item [value]="3">
<p-step>Header III</p-step>
<p-step-panel>
<ng-template #content let-activateCallback="activateCallback">
<div class="flex flex-col h-48">
<div
class="border-2 border-dashed border-surface-200 dark:border-surface-700 rounded bg-surface-50 dark:bg-surface-950 flex-auto flex justify-center items-center font-medium"
>
Content III
</div>
</div>
<div class="py-6">
<p-button label="Back" severity="secondary" (onClick)="activateCallback(2)" />
</div>
</ng-template>
</p-step-panel>
</p-step-item>
</p-stepper>
When linear property is set to true, current step must be completed in order to move to the next step.
<p-stepper [value]="1" class="basis-[50rem]" [linear]="true">
<p-step-list>
<p-step [value]="1">Header I</p-step>
<p-step [value]="2">Header II</p-step>
<p-step [value]="3">Header II</p-step>
</p-step-list>
<p-step-panels>
<p-step-panel [value]="1">
<ng-template #content let-activateCallback="activateCallback">
<div class="flex flex-col h-48">
<div
class="border-2 border-dashed border-surface-200 dark:border-surface-700 rounded bg-surface-50 dark:bg-surface-950 flex-auto flex justify-center items-center font-medium"
>
Content I
</div>
<div class="flex pt-6 justify-end">
<p-button label="Next" icon="pi pi-arrow-right" iconPos="right" (onClick)="activateCallback(2)" />
</div>
</div>
</ng-template>
</p-step-panel>
<p-step-panel [value]="2">
<ng-template #content let-activateCallback="activateCallback">
<div class="flex flex-col h-48">
<div
class="border-2 border-dashed border-surface-200 dark:border-surface-700 rounded bg-surface-50 dark:bg-surface-950 flex-auto flex justify-center items-center font-medium"
>
Content II
</div>
</div>
<div class="flex pt-6 justify-between">
<p-button label="Back" severity="secondary" icon="pi pi-arrow-left" (onClick)="activateCallback(1)" />
<p-button label="Next" icon="pi pi-arrow-right" iconPos="right" (onClick)="activateCallback(3)" />
</div>
</ng-template>
</p-step-panel>
<p-step-panel [value]="3">
<ng-template #content let-activateCallback="activateCallback">
<div class="flex flex-col h-48">
<div
class="border-2 border-dashed border-surface-200 dark:border-surface-700 rounded bg-surface-50 dark:bg-surface-950 flex-auto flex justify-center items-center font-medium"
>
Content III
</div>
</div>
<div class="flex pt-6 justify-start">
<p-button label="Back" icon="pi pi-arrow-left" iconPos="right" (onClick)="activateCallback(2)" />
</div>
</ng-template>
</p-step-panel>
</p-step-panels>
</p-stepper>
Use Stepper with a StepList only for custom requirements where a progress indicator is needed.
<p-stepper [value]="1" class="basis-[50rem]">
<p-step-list>
<p-step [value]="1">Design</p-step>
<p-step [value]="2">Development</p-step>
<p-step [value]="3">QA</p-step>
</p-step-list>
</p-stepper>
Stepper provides various templating options to customize the default UI design.
<p-stepper [(value)]="activeStep" class="basis-[40rem]">
<p-step-list>
<p-step [value]="1" class="flex flex-row flex-auto gap-2">
<ng-template #content let-activateCallback="activateCallback" let-value="value">
<button class="bg-transparent border-0 inline-flex flex-col gap-2" (click)="activateCallback()">
<span
class="rounded-full border-2 w-12 h-12 inline-flex items-center justify-center"
[ngClass]="{
'bg-primary text-primary-contrast border-primary': value <= activeStep,
'border-surface': value > activeStep
}"
>
<i class="pi pi-user"></i>
</span>
</button>
</ng-template>
</p-step>
<p-step [value]="2" class="flex flex-row flex-auto gap-2">
<ng-template #content let-activateCallback="activateCallback" let-value="value">
<button class="bg-transparent border-0 inline-flex flex-col gap-2" (click)="activateCallback()">
<span
class="rounded-full border-2 w-12 h-12 inline-flex items-center justify-center"
[ngClass]="{
'bg-primary text-primary-contrast border-primary': value <= activeStep,
'border-surface': value > activeStep
}"
>
<i class="pi pi-star"></i>
</span>
</button>
</ng-template>
</p-step>
<p-step [value]="3" class="flex flex-row flex-auto gap-2">
<ng-template #content let-activateCallback="activateCallback" let-value="value">
<button class="bg-transparent border-0 inline-flex flex-col gap-2" (click)="activateCallback()">
<span
class="rounded-full border-2 w-12 h-12 inline-flex items-center justify-center"
[ngClass]="{
'bg-primary text-primary-contrast border-primary': value <= activeStep,
'border-surface': value > activeStep
}"
>
<i class="pi pi-id-card"></i>
</span>
</button>
</ng-template>
</p-step>
</p-step-list>
<p-step-panels>
<p-step-panel [value]="1">
<ng-template #content let-activateCallback="activateCallback">
<div class="flex flex-col gap-2 mx-auto" style="min-height: 16rem; max-width: 20rem">
<div class="text-center mt-4 mb-4 text-xl font-semibold">Create your account</div>
<div class="field">
<input [(ngModel)]="name" pInputText id="input" type="text" placeholder="Name" fluid />
</div>
<div class="field">
<input [(ngModel)]="email" pInputText id="email" type="email" placeholder="Email" fluid />
</div>
<div class="field">
<p-password [(ngModel)]="password" placeholder="Password" fluid />
</div>
</div>
<div class="flex pt-6 justify-end">
<p-button (onClick)="activateCallback(2)" label="Next" icon="pi pi-arrow-right" iconPos="right" />
</div>
</ng-template>
</p-step-panel>
<p-step-panel [value]="2">
<ng-template #content let-activateCallback="activateCallback">
<div class="flex flex-col gap-2 mx-auto" style="min-height: 16rem; max-width: 24rem">
<div class="text-center mt-4 mb-4 text-xl font-semibold">Choose your interests</div>
<div class="flex flex-wrap justify-center gap-4">
<p-togglebutton [(ngModel)]="option1" onLabel="Nature" offLabel="Nature" />
<p-togglebutton [(ngModel)]="option2" onLabel="Art" offLabel="Art" />
<p-togglebutton [(ngModel)]="option3" onLabel="Music" offLabel="Music" />
<p-togglebutton [(ngModel)]="option4" onLabel="Design" offLabel="Design" />
<p-togglebutton [(ngModel)]="option5" onLabel="Photography" offLabel="Photography" />
<p-togglebutton [(ngModel)]="option6" onLabel="Movies" offLabel="Movies" />
<p-togglebutton [(ngModel)]="option7" onLabel="Sports" offLabel="Sports" />
<p-togglebutton [(ngModel)]="option8" onLabel="Gaming" offLabel="Gaming" />
<p-togglebutton [(ngModel)]="option9" onLabel="Traveling" offLabel="Traveling" />
<p-togglebutton [(ngModel)]="option10" onLabel="Dancing" offLabel="Dancing" />
</div>
</div>
<div class="flex pt-6 justify-between">
<p-button (onClick)="activateCallback(1)" label="Back" severity="secondary" icon="pi pi-arrow-left" />
<p-button (onClick)="activateCallback(3)" label="Next" icon="pi pi-arrow-right" iconPos="right" />
</div>
</ng-template>
</p-step-panel>
<p-step-panel [value]="3">
<ng-template #content let-activateCallback="activateCallback">
<div class="flex flex-col gap-2 mx-auto" style="min-height: 16rem; max-width: 24rem">
<div class="text-center mt-4 mb-4 text-xl font-semibold">Account created successfully</div>
<div class="text-center">
<img alt="logo" src="https://primefaces.org/cdn/primeng/images/stepper/content.svg" />
</div>
</div>
<div class="flex pt-6 justify-start">
<p-button (onClick)="activateCallback(2)" label="Back" severity="secondary" icon="pi pi-arrow-left" />
</div>
</ng-template>
</p-step-panel>
</p-step-panels>
</p-stepper>
Stepper container is defined with the tablist role, as any attribute is passed to the container element aria-labelledby can be optionally used to specify an element to describe the Stepper. Each stepper header has a tab role and aria-controls to refer to the corresponding stepper content element. The content element of each stepper has tabpanel role, an id to match the aria-controls of the header and aria-labelledby reference to the header as the accessible name.
Key | Function |
---|---|
tab | Moves focus through the header. |
enter | Activates the focused stepper header. |
space | Activates the focused stepper header. |