---
title: "Stepper"
description: "A set of steps that are used to indicate progress through a multi-step process."
canonical_url: "https://vinicunca.dev/akar/components/stepper"
---
# Stepper

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

```vue [index.vue]
<script setup lang="ts">
import { akarDemoIcon } from '../akar-demo-icons'
import { StepperDescription, StepperIndicator, StepperItem, StepperRoot, StepperSeparator, StepperTitle, StepperTrigger } from 'akar'
import './styles.css'

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>
  <div class="akar-demo akar-demo-Stepper">
    <StepperRoot
        :default-value="2"
        class="StepperList"
      >
        <StepperItem
          v-for="item in steps"
          :key="item.step"
          class="StepperItem"
          :step="item.step"
        >
          <StepperTrigger class="StepperTrigger">
            <StepperIndicator
              class="StepperIndicator"
            >
              <PIcon
                :name="akarDemoIcon(item.icon)"
                class="StepperIndicatorIcon"
              />
            </StepperIndicator>
            <div class="StepperItemText">
              <StepperTitle class="StepperTitle">
                {{ item.title }}
              </StepperTitle>
              <StepperDescription class="StepperDescription">
                {{ item.description }}
              </StepperDescription>
            </div>
          </StepperTrigger>
          <StepperSeparator
            v-if="item.step !== steps[steps.length - 1].step"
            class="StepperSeparator"
          />
        </StepperItem>
      </StepperRoot>
  </div>
</template>
```

```css [styles.css]
@import '../_colors/grass.css';
@import '../_colors/mauve.css';
@import '../_colors/green.css';

@scope (.akar-demo-Stepper) {
.StepperList {
  display: flex;
  gap: 1rem;
}

.StepperItem {
  display: flex;
  gap: 1rem;
  align-items: center;
  cursor: pointer;
}

.StepperItem[data-disabled] {
  pointer-events: none;
}

.StepperTrigger {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  align-items: center;
}

.StepperIndicator {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 9999px;
  width: 1.5rem;
  height: 1.5rem;
  color: var(--grass11);
  box-shadow: 0 0 0 2px #000;
}

.StepperItem[data-disabled] .StepperIndicator {
  color: #9ca3af;
}

.StepperItem[data-state="active"] .StepperIndicator {
  background-color: #000;
  color: #fff;
  box-shadow: 0 0 0 2px #000;
}

.StepperItem[data-state="completed"] .StepperIndicator {
  background-color: var(--green9);
  color: #fff;
  box-shadow: 0 0 0 2px var(--green9);
}

.StepperIcon {
  width: 1.5rem;
  height: 1.5rem;
}

.StepperTitle {
  font-size: 0.875rem;
  font-weight: 500;
  color: #000;
}

.StepperDescription {
  font-size: 0.75rem;
  color: #000;
}

.StepperSeparator {
  width: 20px;
  height: 1px;
  flex-shrink: 0;
  background-color: var(--green5);
}

.StepperItem[data-state="active"] .StepperSeparator {
  background-color: #000;
}

.StepperItem[data-state="completed"] .StepperSeparator {
  background-color: var(--green9);
}

.StepperItem[data-disabled] {
  background-color: #d1d5db;
}
}
```

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

```bash [pnpm]
pnpm add akar
```

```bash [yarn]
yarn add akar
```

```bash [npm]
npm install akar
```

```bash [bun]
bun add akar
```

## Anatomy

Import all parts and piece them together.

```vue
<script setup>
import { StepperDescription, StepperIndicator, StepperItem, StepperRoot, StepperTitle, StepperTrigger } from 'akar';
</script>

<template>
  <StepperRoot>
    <StepperItem>
      <StepperTrigger />
      <StepperIndicator />

      <StepperTitle />
      <StepperDescription />

      <StepperSeparator />
    </StepperItem>
  </StepperRoot>
</template>
```

## API Reference

### Root

Contains all the stepper component parts.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `defaultValue` | `1` | `number` | The value of the step that should be active when initially rendered. Use when you do not need to control the state of the steps. |
| `dir` |  | `"ltr" \| "rtl"` | The reading direction of the combobox when applicable.<br><br>If omitted, inherits globally from `ConfigProvider` 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 step to activate. Can be bound as `v-model`. |
| `orientation` | `"horizontal"` | `"vertical" \| "horizontal"` | The orientation the steps are laid out.<br>Mainly so arrow navigation is done accordingly (left & right vs. up & down). |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `update:modelValue` | `payload: number` | Event handler called when the value changes |

**Slots**

| Slot | Payload | Description |
| --- | --- | --- |
| `modelValue` | `number` | Current step |
| `totalSteps` | `number` | Total number of steps |
| `isNextDisabled` | `boolean` | Whether or not the next step is disabled |
| `isPrevDisabled` | `boolean` | Whether or not the previous step is disabled |
| `isFirstStep` | `boolean` | Whether or not the first step is active |
| `isLastStep` | `boolean` | Whether or not the last step is active |
| `goToStep` | `(step: number): void` | Go to a specific step |
| `nextStep` | `(): void` | Go to the next step |
| `prevStep` | `(): void` | Go to the previous step |
| `hasNext` | `(): boolean` | Whether or not there is a next step |
| `hasPrev` | `(): boolean` | Whether or not there is a previous step |

**Methods**

| Method | Type | Description |
| --- | --- | --- |
| `goToStep` | `(step: number) => void` |  |
| `nextStep` | `() => void` |  |
| `prevStep` | `() => void` |  |
| `hasNext` | `() => boolean` |  |
| `hasPrev` | `() => boolean` |  |

[StepperRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Stepper/StepperRoot.vue)

| Data attribute | Value |
| --- | --- |
| `[data-orientation]` | "vertical" \\| "horizontal" |
| `[data-linear]` | Present when linear |

### Item

The step item component.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/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 step. |
| `step*` |  | `number` | A unique value that associates the stepper item with an index |

**Slots**

| Slot | Payload | Description |
| --- | --- | --- |
| `state` | `"active" \| "completed" \| "inactive"` | The current state of the stepper item |

[StepperItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Stepper/StepperItem.vue)

| Data attribute | Value |
| --- | --- |
| `[data-state]` | "active" \\| "inactive" \\| "completed" |
| `[data-disabled]` | Present when disabled |
| `[data-orientation]` | "vertical" \\| "horizontal" |

### Trigger

The trigger that toggles the step.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |

[StepperTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Stepper/StepperTrigger.vue)

| Data attribute | Value |
| --- | --- |
| `[data-state]` | "active" \\| "inactive" \\| "completed" |
| `[data-disabled]` | Present when disabled |
| `[data-orientation]` | "vertical" \\| "horizontal" |

### Indicator

The indicator for the step.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |

**Slots**

| Slot | Payload | Description |
| --- | --- | --- |
| `step` | `number` | Current step |

[StepperIndicator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Stepper/StepperIndicator.vue)

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

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"h4"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |

[StepperTitle.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Stepper/StepperTitle.vue)

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

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/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 step. |
| `step*` |  | `number` | A unique value that associates the stepper item with an index |

**Slots**

| Slot | Payload | Description |
| --- | --- | --- |
| `state` | `"active" \| "completed" \| "inactive"` | The current state of the stepper item |

[StepperItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Stepper/StepperItem.vue)

## Examples

### Vertical

You can create vertical steps by using the `orientation` prop.

```vue
<script setup>
import { StepperDescription, StepperIndicator, StepperItem, StepperRoot, StepperTitle } from 'akar'
</script>

<template>
  <StepperRoot
    :default-value="1"
    orientation="vertical"
  >
    <StepperItem>
      <StepperIndicator />
      <StepperTitle />
      <StepperDescription />
    </StepperItem>
    <StepperItem>
      <StepperIndicator />
      <StepperTitle />
      <StepperDescription />
    </StepperItem>
  </StepperRoot>
</template>
```

### With controls

You can add additional controls for the stepper using buttons and access the typed component instance using `useTemplateRef`.

```vue
<script setup lang="ts">
const stepper = useTemplateRef('stepper')
</script>

<template>
  <StepperRoot
    ref="stepper"
    :default-value="1"
  >
    <StepperItem>
      <StepperIndicator />
      <StepperTitle />
      <StepperDescription />
    </StepperItem>
    <StepperItem>
      <StepperIndicator />
      <StepperTitle />
      <StepperDescription />
    </StepperItem>
  </StepperRoot>

  <div class="flex gap-2 justify-between mt-4">
    <button
      :disabled="!stepper?.hasPrev()"
      @click="stepper?.prevStep()"
    >
      Prev
    </button>

    <button
      :disabled="!stepper?.hasNext()"
      @click="stepper?.nextStep()"
    >
      Next
    </button>
  </div>
</template>
```

## Accessibility

### Keyboard Interactions

| Key | Description |
| --- | --- |
| <kbd>Tab</kbd> |  When focus moves onto the steps, focuses the first step . |
| <kbd>ArrowDown</kbd> |  Moves focus to the next step depending on `orientation`. |
| <kbd>ArrowRight</kbd> |  Moves focus to the next step depending on `orientation` . |
| <kbd>ArrowUp</kbd> |  Moves focus to the previous step depending on `orientation` . |
| <kbd>ArrowLeft</kbd> |  Moves focus to the previous step depending on `orientation` . |
| <kbd>Enter</kbd> / <kbd>Space</kbd> | Selects the focused step. |

---

- [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Stepper)
- [npm](https://www.npmjs.com/package/akar)


## Sitemap

See the full [sitemap](https://vinicunca.dev/sitemap.md) for all pages.
