npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@doderasoftware/vue-stepper

v1.0.9

Published

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,

Downloads

1,024

Readme

@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