# Steps

URL: https://ark-ui.com/docs/components/steps
Source: https://raw.githubusercontent.com/chakra-ui/ark/refs/heads/main/website/src/content/pages/components/steps.mdx

Used to guide users through a series of steps in a process

---

<ComponentPreview id="Steps" />

## Anatomy

<Anatomy id="steps" />

```tsx
<Steps.Root>
  <Steps.List>
    <Steps.Item>
      <Steps.Trigger>
        <Steps.Indicator />
      </Steps.Trigger>
      <Steps.Separator />
    </Steps.Item>
  </Steps.List>
  <Steps.Content />
  <Steps.CompletedContent />
  <Steps.PrevTrigger />
  <Steps.NextTrigger />
</Steps.Root>
```

## Examples

### Basic

Here's a basic example of the `Steps` component.

<Example component="steps" id="basic" />

### Controlled

Using the `RootProvider` component, you can control the active step by using the `step` prop and handling the
`onStepChange` event.

**Example: controlled**

```ripple
import { Steps } from 'ark-ripple/steps';
import { track } from 'ripple';
import button from 'styles/button.module.css';
import styles from 'styles/steps.module.css';

const items = [
  { value: 'first', title: 'First', description: 'Contact Info' },
  { value: 'second', title: 'Second', description: 'Date & Time' },
  { value: 'third', title: 'Third', description: 'Select Rooms' },
];

export component Controlled() {
  let step = track(0);

  <div class="stack">
    <output>
      {'current step: '}
      {@step + 1}
    </output>

    <Steps.Root
      class={styles.Root}
      count={items.length}
      {step}
      onStepChange={(details) => {
        @step = details.step;
      }}
    >
      <Steps.List class={styles.List}>
        for (const item of items; index index; key item.value) {
          <Steps.Item class={styles.Item} {index}>
            <Steps.Trigger class={styles.Trigger}>
              <Steps.Indicator class={styles.Indicator}>{index + 1}</Steps.Indicator>
              <span>{item.title}</span>
            </Steps.Trigger>
            <Steps.Separator class={styles.Separator} />
          </Steps.Item>
        }
      </Steps.List>

      for (const item of items; index index; key item.value) {
        <Steps.Content class={styles.Content} {index}>
          {item.title}
          {' - '}
          {item.description}
        </Steps.Content>
      }

      <Steps.CompletedContent class={styles.CompletedContent}>
        {'Steps Complete - Thank you for filling out the form!'}
      </Steps.CompletedContent>

      <div class={styles.Actions}>
        <Steps.PrevTrigger class={button.Root}>{'Back'}</Steps.PrevTrigger>
        <Steps.NextTrigger class={button.Root} data-variant="solid">{'Next'}</Steps.NextTrigger>
      </div>
    </Steps.Root>
  </div>
}

```

### Root Provider

An alternative way to control the steps is to use the `RootProvider` component and the `useSteps` hook. This way you can
access the state and methods from outside the component.

**Example: root-provider**

```ripple
import { Steps, useSteps } from 'ark-ripple/steps';
import button from 'styles/button.module.css';
import styles from 'styles/steps.module.css';

const items = [
  { value: 'first', title: 'First', description: 'Contact Info' },
  { value: 'second', title: 'Second', description: 'Date & Time' },
  { value: 'third', title: 'Third', description: 'Select Rooms' },
];

export component RootProvider() {
  const stepsApi = useSteps({ count: items.length });

  <div class="stack">
    <output>
      {'current step: '}
      {@stepsApi.value + 1}
    </output>

    <Steps.RootProvider class={styles.Root} value={stepsApi}>
      <Steps.List class={styles.List}>
        for (const item of items; index index; key item.value) {
          <Steps.Item class={styles.Item} {index}>
            <Steps.Trigger class={styles.Trigger}>
              <Steps.Indicator class={styles.Indicator}>{index + 1}</Steps.Indicator>
              <span>{item.title}</span>
            </Steps.Trigger>
            <Steps.Separator class={styles.Separator} />
          </Steps.Item>
        }
      </Steps.List>

      for (const item of items; index index; key item.value) {
        <Steps.Content class={styles.Content} {index}>
          {item.title}
          {' - '}
          {item.description}
        </Steps.Content>
      }

      <Steps.CompletedContent class={styles.CompletedContent}>
        {'Steps Complete - Thank you for filling out the form!'}
      </Steps.CompletedContent>

      <div class={styles.Actions}>
        <Steps.PrevTrigger class={button.Root}>{'Back'}</Steps.PrevTrigger>
        <Steps.NextTrigger class={button.Root} data-variant="solid">{'Next'}</Steps.NextTrigger>
      </div>
    </Steps.RootProvider>
  </div>
}

```

### Vertical

Use the `orientation` prop to display the steps vertically.

**Example: vertical**

```ripple
import { Steps } from 'ark-ripple/steps';
import button from 'styles/button.module.css';
import styles from 'styles/steps.module.css';

const items = [
  { value: 'first', title: 'First', description: 'Contact Info' },
  { value: 'second', title: 'Second', description: 'Date & Time' },
  { value: 'third', title: 'Third', description: 'Select Rooms' },
];

export component Vertical() {
  <Steps.Root class={styles.Root} count={items.length} orientation="vertical">
    <Steps.List class={styles.List}>
      for (const item of items; index index; key item.value) {
        <Steps.Item class={styles.Item} {index}>
          <Steps.Trigger class={styles.Trigger}>
            <Steps.Indicator class={styles.Indicator}>{index + 1}</Steps.Indicator>
            <span>{item.title}</span>
          </Steps.Trigger>
          <Steps.Separator class={styles.Separator} />
        </Steps.Item>
      }
    </Steps.List>

    for (const item of items; index index; key item.value) {
      <Steps.Content class={styles.Content} {index}>
        <div class="vstack">
          <span>
            {item.title}
            {' - '}
            {item.description}
          </span>
          <div class={styles.Actions}>
            <Steps.PrevTrigger class={button.Root}>{'Back'}</Steps.PrevTrigger>
            <Steps.NextTrigger class={button.Root} data-variant="solid">{'Next'}</Steps.NextTrigger>
          </div>
        </div>
      </Steps.Content>
    }

    <Steps.CompletedContent class={styles.CompletedContent}>
      <div class="vstack">
        <span>{'Steps Complete - Thank you for filling out the form!'}</span>
        <Steps.PrevTrigger class={button.Root}>{'Back'}</Steps.PrevTrigger>
      </div>
    </Steps.CompletedContent>
  </Steps.Root>
}

```

## API Reference

### Props

**Component API Reference**

**Root Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `count` | `number` | No | The total number of steps |
| `defaultStep` | `number` | No | The initial value of the stepper when rendered.
Use when you don't need to control the value of the stepper. |
| `ids` | `ElementIds` | No | The custom ids for the stepper elements |
| `isStepSkippable` | `(index: number) => boolean` | No | Whether a step can be skipped during navigation.
Skippable steps are bypassed when using next/prev. |
| `isStepValid` | `(index: number) => boolean` | No | Whether a step is valid. Invalid steps block forward navigation in linear mode. |
| `linear` | `boolean` | No | If `true`, the stepper requires the user to complete the steps in order |
| `onStepChange` | `(details: StepChangeDetails) => void` | No | Callback to be called when the value changes |
| `onStepComplete` | `VoidFunction` | No | Callback to be called when a step is completed |
| `onStepInvalid` | `(details: StepInvalidDetails) => void` | No | Called when navigation is blocked due to an invalid step. |
| `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the stepper |
| `step` | `number` | No | The controlled value of the stepper |


**Root Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | steps |
| `[data-part]` | root |
| `[data-orientation]` | The orientation of the steps |


**Root CSS Variables:**

| Variable | Description |
|----------|-------------|
| `--percent` | The percent value for the Root |


**CompletedContent Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Content Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `index` | `number` | Yes |  |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Content Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | steps |
| `[data-part]` | content |
| `[data-state]` | "open" | "closed" |
| `[data-orientation]` | The orientation of the content |


**Indicator Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Indicator Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | steps |
| `[data-part]` | indicator |
| `[data-complete]` | Present when the indicator value is complete |
| `[data-current]` | Present when current |
| `[data-incomplete]` |  |


**Item Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `index` | `number` | Yes |  |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Item Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | steps |
| `[data-part]` | item |
| `[data-orientation]` | The orientation of the item |
| `[data-skippable]` |  |


**List Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**List Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | steps |
| `[data-part]` | list |
| `[data-orientation]` | The orientation of the list |


**NextTrigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**PrevTrigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Progress Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Progress Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | steps |
| `[data-part]` | progress |
| `[data-complete]` | Present when the progress value is complete |


**RootProvider Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `UseStepsReturn` | Yes |  |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Separator Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Separator Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | steps |
| `[data-part]` | separator |
| `[data-orientation]` | The orientation of the separator |
| `[data-complete]` | Present when the separator value is complete |
| `[data-current]` | Present when current |
| `[data-incomplete]` |  |


**Trigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Trigger Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | steps |
| `[data-part]` | trigger |
| `[data-state]` | "open" | "closed" |
| `[data-orientation]` | The orientation of the trigger |
| `[data-complete]` | Present when the trigger value is complete |
| `[data-current]` | Present when current |
| `[data-incomplete]` |  |


### Context

**API:**

| Property | Type | Description |
|----------|------|-------------|
| `value` | `number` | The value of the stepper. |
| `percent` | `number` | The percentage of the stepper. |
| `count` | `number` | The total number of steps. |
| `hasNextStep` | `boolean` | Whether the stepper has a next step. |
| `hasPrevStep` | `boolean` | Whether the stepper has a previous step. |
| `isCompleted` | `boolean` | Whether the stepper is completed. |
| `isStepValid` | `(index: number) => boolean` | Check if a specific step is valid (lazy evaluation) |
| `isStepSkippable` | `(index: number) => boolean` | Check if a specific step can be skipped |
| `setStep` | `(step: number) => void` | Function to set the value of the stepper. |
| `goToNextStep` | `VoidFunction` | Function to go to the next step. |
| `goToPrevStep` | `VoidFunction` | Function to go to the previous step. |
| `resetStep` | `VoidFunction` | Function to go to reset the stepper. |
| `getItemState` | `(props: ItemProps) => ItemState` | Returns the state of the item at the given index. |
