# Stepper

> A multi-step flow in a frosted panel, with a gliding step indicator, spring transitions and number, dot, bar or vertical layouts.

A multi-step flow in a frosted panel. Click Continue or Back, or click a step in the indicator row to jump to it. A tile glides to the current step, finished steps get a drawn check, the content slides between steps and the panel height springs to fit. Steps can have a title, a description and an icon. Choose numbers, dots or bars across the top, or a vertical rail beside the content. In the demo the Continue button stays disabled on the Profile step until you type a name.

<demo-stepper>



</demo-stepper>

## Installation

```bash
npx shadcn-vue@latest add "https://nxui.geoql.in/r/stepper.json"
```

## Usage

```vue
<script setup lang="ts">
  import { ref } from 'vue';
  import Stepper from '~/components/ui/stepper/Stepper.vue';
  import StepperStep from '~/components/ui/stepper/StepperStep.vue';

  const step = ref(1);
  const name = ref('');
</script>

<template>
  <Stepper
    v-model:step="step"
    :next-button-props="{ disabled: step === 2 && !name }"
    @final-step-completed="console.log('done')"
  >
    <StepperStep title="Welcome">
      <h3>Welcome aboard</h3>
    </StepperStep>
    <StepperStep title="Profile">
      <input v-model="name" placeholder="Your name" />
    </StepperStep>
    <StepperStep title="Review">
      <h3>Looking good, {{ name }}</h3>
    </StepperStep>

    <template #completed>
      <h3>Workspace ready</h3>
    </template>
  </Stepper>

  <!-- Vertical rail with icons and descriptions -->
  <Stepper orientation="vertical" :width="640" accent-color="#4763eb">
    <StepperStep title="Cart" description="2 items" icon="lucide:shopping-cart">
      …
    </StepperStep>
    <StepperStep
      title="Shipping"
      description="Delivery speed"
      icon="lucide:truck"
    >
      …
    </StepperStep>
  </Stepper>
</template>
```

Inside the panel, the CSS variables `--stepper-ink`, `--stepper-muted`, `--stepper-well`, `--stepper-tile`, `--stepper-tile-edge` and `--stepper-ring` are available, so your step content can match the theme. The vertical rail folds into a row when the stepper is narrower than 520px, and step titles hide when the row cannot fit them.

## Props

<table>
<thead>
  <tr>
    <th>
      Prop
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Default
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        v-model:step
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      The current step. Leave it unbound to let the stepper keep its own step.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        initial-step
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      The step shown first when <code>
        v-model:step
      </code>
      
       is not used.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        indicator
      </code>
    </td>
    
    <td>
      <code>
        'numbers' | 'dots' | 'bars'
      </code>
    </td>
    
    <td>
      <code>
        'numbers'
      </code>
    </td>
    
    <td>
      Style of the step indicators in the horizontal layout.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        orientation
      </code>
    </td>
    
    <td>
      <code>
        'horizontal' | 'vertical'
      </code>
    </td>
    
    <td>
      <code>
        'horizontal'
      </code>
    </td>
    
    <td>
      Indicators across the top, or a rail of numbered steps beside the content.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        transition
      </code>
    </td>
    
    <td>
      <code>
        'slide' | 'fade' | 'none'
      </code>
    </td>
    
    <td>
      <code>
        'slide'
      </code>
    </td>
    
    <td>
      How the content changes between steps. The height always animates.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        linear
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Only lets the indicators jump back to steps that have been reached.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        disable-step-indicators
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Stops the indicators from changing the step when clicked.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        show-footer
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Shows the Back and Continue buttons.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        back-button-text
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'Back'
      </code>
    </td>
    
    <td>
      Text of the Back button.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        next-button-text
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'Continue'
      </code>
    </td>
    
    <td>
      Text of the Continue button.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        complete-button-text
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'Complete'
      </code>
    </td>
    
    <td>
      Text of the Continue button on the last step.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        back-button-props
      </code>
    </td>
    
    <td>
      <code>
        ButtonHTMLAttributes
      </code>
    </td>
    
    <td>
      <code>
        {}
      </code>
    </td>
    
    <td>
      Extra attributes for the Back button. An <code>
        onClick
      </code>
      
       that calls <code>
        preventDefault()
      </code>
      
       stops the step change.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        next-button-props
      </code>
    </td>
    
    <td>
      <code>
        ButtonHTMLAttributes
      </code>
    </td>
    
    <td>
      <code>
        {}
      </code>
    </td>
    
    <td>
      Extra attributes for the Continue button, such as <code>
        { disabled: true }
      </code>
      
       while a step is incomplete.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        theme
      </code>
    </td>
    
    <td>
      <code>
        'dark' | 'light'
      </code>
    </td>
    
    <td>
      <code>
        'dark'
      </code>
    </td>
    
    <td>
      Color theme of the panel and controls.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        accent-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Color of finished steps, the bars and the Continue button. Its text color is picked for contrast.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        frame
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Shows the frosted panel around the stepper.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        radius
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        24
      </code>
    </td>
    
    <td>
      Corner radius of the panel, in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        width
      </code>
    </td>
    
    <td>
      <code>
        number | string
      </code>
    </td>
    
    <td>
      <code>
        440
      </code>
    </td>
    
    <td>
      Maximum width of the stepper.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes on the root.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        step-container-class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes on the indicator row.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        content-class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes on the content area.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        footer-class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes on the footer.
    </td>
  </tr>
</tbody>
</table>

### StepperStep props

<table>
<thead>
  <tr>
    <th>
      Prop
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Default
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        title
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Label shown in the indicator row, or beside it in the vertical layout.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        description
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Second line shown beside the indicator in the vertical layout.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        icon
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Iconify name (e.g. <code>
        lucide:truck
      </code>
      
      ) shown instead of the step number.
    </td>
  </tr>
</tbody>
</table>

## Events and slots

<table>
<thead>
  <tr>
    <th>
      Name
    </th>
    
    <th>
      Payload / props
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        step-change
      </code>
      
       event
    </td>
    
    <td>
      <code>
        step: number
      </code>
    </td>
    
    <td>
      Fires when the step changes.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        final-step-completed
      </code>
      
       event
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Fires when the last step is completed.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        default
      </code>
      
       slot
    </td>
    
    <td>
      —
    </td>
    
    <td>
      The steps, one <code>
        StepperStep
      </code>
      
       each.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        #completed
      </code>
      
       slot
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Shown in place of the steps once the last one is completed.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        #indicator
      </code>
      
       slot
    </td>
    
    <td>
      <code>
        { step, currentStep, status, onStepClick }
      </code>
    </td>
    
    <td>
      Replaces the numbered badge with your own indicator.
    </td>
  </tr>
</tbody>
</table>

## Accessibility

- The indicators are buttons with `aria-label="Step N: Title"` and `aria-current="step"` on the current one. Steps that cannot be reached are disabled.
- The content area is an `aria-live` region, so the new step is announced. If focus was inside the old step, it moves to the new one.
- Buttons and indicators show a visible focus ring.
- With `prefers-reduced-motion: reduce`, the content fades instead of sliding and the glider jumps instead of springing.
- Ported from [React Bits](https://reactbits.dev/components/stepper) by David Haz.
