Skip to content

Stepper

A set of steps that are used to indicate progress through a multi-step process.

Address

Shipping

Checkout

Step 2 of 0
vue
<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.

sh
$ npm add radix-vue

Anatomy

Import all parts and piece them together.

vue
<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.

PropDefaultType
as
'div'
AsTag | Component

The element or component this component should render as. Can be overwrite by asChild

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.
If omitted, inherits globally from DirectionProvider or assumes LTR (left-to-right) reading mode.

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 v-model.

orientation
'horizontal'
'vertical' | 'horizontal'

The orientation the tabs are laid out. Mainly so arrow navigation is done accordingly (left & right vs. up & down)

EmitPayload
update:modelValue
[payload: number]

Event handler called when the value changes

Slots (default)Payload
modelValue
number | undefined

Current step

Data AttributeValue
[data-orientation]"vertical" | "horizontal"
[data-linear]Present when linear

Item

The step item component.

PropDefaultType
as
'div'
AsTag | Component

The element or component this component should render as. Can be overwrite by asChild

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 true, prevents the user from interacting with the tab.

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 AttributeValue
[data-state]"active" | "inactive" | "completed"
[data-disabled]Present when disabled
[data-orientation]"vertical" | "horizontal"

Trigger

The trigger that toggles the step.

PropDefaultType
as
'button'
AsTag | Component

The element or component this component should render as. Can be overwrite by asChild

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 AttributeValue
[data-state]"active" | "inactive" | "completed"
[data-disabled]Present when disabled
[data-orientation]"vertical" | "horizontal"

Indicator

The indicator for the step.

PropDefaultType
as
'div'
AsTag | Component

The element or component this component should render as. Can be overwrite by asChild

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>.

PropDefaultType
as
'h4'
AsTag | Component

The element or component this component should render as. Can be overwrite by asChild

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.

PropDefaultType
as
'div'
AsTag | Component

The element or component this component should render as. Can be overwrite by asChild

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 true, prevents the user from interacting with the tab.

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.

vue
<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

KeyDescription
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.