Stepper
Address
Add your address here
Shipping
Set your preferred shipping method
Checkout
Confirm your order
<script setup lang="ts">
import { Icon } from '@iconify/vue'
import { StepperDescription, StepperIndicator, StepperItem, StepperRoot, StepperSeparator, StepperTitle, StepperTrigger } from 'radix-vue'
const steps = [{
step: 1,
title: 'Address',
description: 'Add your address here',
icon: 'radix-icons:home',
}, {
step: 2,
title: 'Shipping',
description: 'Set your preferred shipping method',
icon: 'radix-icons:archive',
}, {
step: 3,
title: 'Checkout',
description: 'Confirm your order',
icon: 'radix-icons:check',
}]
</script>
<template>
<StepperRoot
:default-value="2"
class="flex gap-2 w-full max-w-[32rem]"
>
<StepperItem
v-for="item in steps"
:key="item.step"
class="w-full flex justify-center gap-2 cursor-pointer group data-[disabled]:pointer-events-none relative px-4"
:step="item.step"
>
<StepperTrigger class="inline-flex items-center group-data-[disabled]:text-gray-400 group-data-[state=active]:bg-green11 group-data-[state=active]:text-white justify-center rounded-full text-gray-400 w-10 h-10 shrink-0 bg-gray-300 group-data-[state=completed]:bg-white group-data-[state=completed]:text-green10 focus:shadow-[0_0_0_2px] focus:shadow-black focus:outline-none">
<StepperIndicator>
<Icon
:icon="item.icon"
class="w-5 h-5"
/>
</StepperIndicator>
</StepperTrigger>
<StepperSeparator
v-if="item.step !== steps[steps.length - 1].step"
class="absolute block top-5 left-[calc(50%+30px)] right-[calc(-50%+20px)] h-0.5 rounded-full group-data-[disabled]:bg-gray-300 bg-gray-300 group-data-[state=completed]:bg-white bg-green5 shrink-0"
/>
<div class="absolute text-center top-full left-0 w-full mt-2 text-white group-data-[state=inactive]:text-gray-300">
<StepperTitle class="font-medium">
{{ item.title }}
</StepperTitle>
<StepperDescription class="hidden sm:block text-xs">
{{ item.description }}
</StepperDescription>
</div>
</StepperItem>
</StepperRoot>
</template>
Features
- Can be controlled or uncontrolled.
- Supports horizontal/vertical orientation.
- Supports linear/non-linear activation.
- Full keyboard navigation.
Installation
Install the component from your command line.
$ npm add radix-vue
Anatomy
Import all parts and piece them together.
<script setup>
import { StepperDescription, StepperIndicator, StepperItem, StepperRoot, StepperTitle, StepperTrigger } from 'radix-vue'
</script>
<template>
<StepperRoot>
<StepperItem>
<StepperTrigger />
<StepperIndicator />
<StepperTitle />
<StepperDescription />
<StepperSeparator />
</StepperItem>
</StepperRoot>
</template>
API Reference
Root
Contains all the stepper component parts.
Prop | Default | Type |
---|---|---|
as | 'div' | AsTag | Component The element or component this component should render as. Can be overwrite by |
asChild | boolean Change the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
defaultValue | 1 | number The value of the tab that should be active when initially rendered. Use when you do not need to control the state of the tabs |
dir | 'ltr' | 'rtl' The reading direction of the combobox when applicable. | |
linear | true | boolean Whether or not the steps must be completed in order |
modelValue | number The controlled value of the tab to activate. Can be bound as | |
orientation | 'horizontal' | 'vertical' | 'horizontal' The orientation the tabs are laid out. Mainly so arrow navigation is done accordingly (left & right vs. up & down) |
Emit | Payload |
---|---|
update:modelValue | [payload: number] Event handler called when the value changes |
Slots (default) | Payload |
---|---|
modelValue | number | undefined Current step |
Data Attribute | Value |
---|---|
[data-orientation] | "vertical" | "horizontal" |
[data-linear] | Present when linear |
Item
The step item component.
Prop | Default | Type |
---|---|---|
as | 'div' | AsTag | Component The element or component this component should render as. Can be overwrite by |
asChild | boolean Change the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
completed | false | boolean Shows whether the step is completed. |
disabled | false | boolean When |
step* | number A unique value that associates the stepper item with an index |
Slots (default) | Payload |
---|---|
state | 'active' | 'completed' | 'inactive' The current state of the stepper item |
Data Attribute | Value |
---|---|
[data-state] | "active" | "inactive" | "completed" |
[data-disabled] | Present when disabled |
[data-orientation] | "vertical" | "horizontal" |
Trigger
The trigger that toggles the step.
Prop | Default | Type |
---|---|---|
as | 'button' | AsTag | Component The element or component this component should render as. Can be overwrite by |
asChild | boolean Change the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. |
Data Attribute | Value |
---|---|
[data-state] | "active" | "inactive" | "completed" |
[data-disabled] | Present when disabled |
[data-orientation] | "vertical" | "horizontal" |
Indicator
The indicator for the step.
Prop | Default | Type |
---|---|---|
as | 'div' | AsTag | Component The element or component this component should render as. Can be overwrite by |
asChild | boolean Change the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. |
Title
An accessible title to be announced when the stepper trigger is focused.
If you want to hide the title, wrap it inside our Visually Hidden utility like this <VisuallyHidden asChild>
.
Prop | Default | Type |
---|---|---|
as | 'h4' | AsTag | Component The element or component this component should render as. Can be overwrite by |
asChild | boolean Change the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. |
Description
An optional accessible description to be announced when the stepper trigger is focused.
If you want to hide the description, wrap it inside our Visually Hidden utility like this <VisuallyHidden asChild>
. If you want to remove the description entirely, remove this part and pass aria-describedby="undefined"
to StepperTrigger
.
Prop | Default | Type |
---|---|---|
as | 'div' | AsTag | Component The element or component this component should render as. Can be overwrite by |
asChild | boolean Change the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
completed | false | boolean Shows whether the step is completed. |
disabled | false | boolean When |
step* | number A unique value that associates the stepper item with an index |
Slots (default) | Payload |
---|---|
state | 'active' | 'completed' | 'inactive' The current state of the stepper item |
Examples
Vertical
You can create vertical tabs by using the orientation
prop.
<script setup>
import { StepperDescription, StepperIndicator, StepperItem, StepperList, StepperRoot, StepperTitle } from 'radix-vue'
</script>
<template>
<StepperRoot
:default-value="1"
orientation="vertical"
>
<StepperList aria-label="stepper example">
<StepperItem>
<StepperIndicator />
<StepperTitle />
<StepperDescription />
</StepperItem>
<StepperItem>
<StepperIndicator />
<StepperTitle />
<StepperDescription />
</StepperItem>
</StepperList>
</StepperRoot>
</template>
Accessibility
Keyboard Interactions
Key | Description |
---|---|
Tab | When focus moves onto the steps, focuses the first step . |
ArrowDown | Moves focus to the next step depending on orientation . |
ArrowRight | Moves focus to the next step depending on orientation . |
ArrowUp | Moves focus to the previous step depending on orientation . |
ArrowLeft | Moves focus to the previous step depending on orientation . |
EnterSpace | Selects the focused step. |