@doderasoftware/vue-stepper

A headless, accessible, and fully customizable multi-step stepper component for Vue 3. Build complex forms, wizards, and onboarding flows with ease. Features TypeScript support, responsive mobile design, step validation, optional steps, progress tracking,
1,930
Install
npm install @doderasoftware/vue-stepper
Latest Version:1.0.9
Vue:3
License:MIT
Last Updated:Nov 28, 2025
Links: GitHub  ·  npm
Maintainer: doderasoftware

@doderasoftware/vue-stepper

A headless, accessible, and fully customizable multi-step stepper component for Vue 3. Build complex forms, wizards, and onboarding flows with ease.

npm version License: MIT GitHub Documentation

📖 Documentation | 📦 npm | 🐛 Issues

✨ Features

  • 🎨 Fully Customizable - Complete UI control via :ui prop system
  • 🌙 Dark Mode - Built-in dark mode support (follows system preference)
  • 📱 Responsive - Sidebar collapses on mobile with dropdown menu
  • 🔒 Step Locking - Prevent navigation to specific steps
  • ⏭️ Optional Steps - Mark steps as optional with visual indicators
  • 📊 Progress Tracking - Automatic step counters and progress bars
  • 🎯 TypeScript - Full type safety out of the box
  • 🪶 Zero Dependencies - No external CSS frameworks required
  • 🎛️ Headless Ready - Use your own styles or the built-in ones

📦 Installation

npm install @doderasoftware/vue-stepper

That's it! Styles are automatically included - no additional CSS imports needed.

🚀 Quick Start

<template>
  <Stepper
    v-model="currentStep"
    :steps="steps"
    :can-go-next="canProceed"
    sidebar-title="Registration"
    @complete="handleComplete"
  >
    <template #default="{ currentStep: stepIndex }">
      <PersonalInfo v-if="stepIndex === 0" v-model="formData.personal" />
      <AccountDetails v-else-if="stepIndex === 1" v-model="formData.account" />
      <Review v-else-if="stepIndex === 2" :data="formData" />
    </template>
  </Stepper>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import { Stepper } from '@doderasoftware/vue-stepper'

const currentStep = ref(0)
const formData = ref({ personal: {}, account: {} })

const steps = [
  { category: 'Step 1', title: 'Personal Info', description: 'Enter your personal details' },
  { category: 'Step 2', title: 'Account Details', optional: true },
  { category: 'Step 3', title: 'Review & Submit' },
]

const canProceed = computed(() => {
  if (currentStep.value === 0) {
    return !!formData.value.personal.email
  }
  return true
})

function handleComplete() {
  console.log('Form submitted:', formData.value)
}
</script>

🌙 Dark Mode

The component includes full dark mode support out of the box. It uses class-based dark mode - add the dark class to your <html> or <body> element to enable dark styles.

<!-- Enable dark mode via class on html/body -->
<html class="dark">
  ...
</html>

This approach is compatible with most dark mode implementations (Tailwind, manual toggle, etc.).

🎨 UI Customization

The :ui prop allows complete control over every element's styling. Pass class names to override the defaults:

<template>
  <Stepper
    v-model="currentStep"
    :steps="steps"
    :ui="{
      root: 'my-stepper',
      sidebar: 'bg-indigo-50 border-indigo-200',
      navItemCurrent: 'bg-indigo-600 text-white',
      indicatorCompleted: 'bg-indigo-600',
      buttonPrimary: 'bg-gradient-to-r from-indigo-500 to-purple-600 hover:from-indigo-600 hover:to-purple-700',
      progressFill: 'bg-indigo-600',
    }"
  >
    <!-- your content -->
  </Stepper>
</template>

Available UI Keys

Key Description
root Root container
sidebar Desktop sidebar container
sidebarContent Sidebar inner content
sidebarTitle Sidebar title text
nav Navigation container
navItem Step button - base
navItemCurrent Step button - current
navItemCompleted Step button - completed
navItemDisabled Step button - disabled
indicator Step indicator - base
indicatorCurrent Step indicator - current
indicatorCompleted Step indicator - completed
indicatorDisabled Step indicator - disabled
stepCategory Step category text
stepTitle Step title text
progressBar Progress bar track
progressFill Progress bar fill
main Main content area
card Content card
navigation Navigation buttons container
button Button base
buttonPrimary Primary button (next/complete)
buttonSecondary Secondary button (back)
buttonDisabled Disabled button state

📋 Props

Prop Type Default Description
modelValue number 0 Current step index (v-model)
steps StepConfig[] required Array of step configurations
ui StepperUI {} UI customization object
sidebarTitle string 'Steps' Title displayed above the sidebar
canGoNext boolean true Whether user can proceed to next step
nextButtonText string 'Continue' Text for the next button
backButtonText string 'Back' Text for the back button
completeButtonText string 'Complete' Text for the final step button
showNavigation boolean true Show/hide navigation buttons
showProgress boolean true Show/hide progress indicator
showMobileHeader boolean true Show/hide mobile header
showSidebar boolean true Show/hide desktop sidebar
linear boolean true Restrict navigation to sequential steps only

📡 Events

Event Payload Description
update:modelValue number Emitted when step index changes
step-change { from: number, to: number } Emitted on step navigation
next StepChangeEvent Emitted when next button is clicked
back StepChangeEvent Emitted when back button is clicked
complete void Emitted when completing the last step

🎰 Slots

Slot Props Description
default { currentStep, currentStepConfig, goNext, goBack, ... } Main content area
header - Content above the step container
title - Title area inside step container
sidebar-header - Custom sidebar header
sidebar-footer - Custom sidebar footer
step-indicator { step, index, isCurrent, isCompleted, isDisabled } Custom step indicator
back-icon - Custom back button icon
next-icon - Custom next button icon

📐 Step Configuration

interface StepConfig {
  id?: string | number
  category: string
  title: string
  disabled?: boolean
  optional?: boolean
}

🪝 Composable

Use the useMultiStep composable for headless control:

import { useMultiStep } from '@doderasoftware/vue-stepper'

const {
  currentStep,
  isFirstStep,
  isLastStep,
  progress,
  goNext,
  goBack,
  goToStep,
  isStepCompleted,
  reset,
} = useMultiStep({
  steps: mySteps,
  initialStep: 0,
  linear: true,
  onStepChange: ({ from, to }) => console.log(`Step changed from ${from} to ${to}`),
})

🔗 Links

📄 License

MIT © Dodera Software SRL

Related Packages

@smart-wizard/vue

Vue bindings for SmartWizard - modern, framework-agnostic wizard/stepper compone...

489 0
@wizzard-packages/vue

Vue 3 composition API and components for Wizzard Stepper.

5,012 1
@smart-wizard/core

Core logic for SmartWizard - modern, framework-agnostic wizard/stepper component

641 0
@smart-wizard/extension-url-hash

URL hash + browser history navigation extension for SmartWizard

494 0

Version History

Version Released Vue License
1.0.9 ^3.3.0 MIT
1.0.8 ^3.3.0 MIT
1.0.7 ^3.3.0 MIT
1.0.6 ^3.3.0 MIT
1.0.5 ^3.3.0 MIT