@gooonzick/wizard-vue

Vue 3 integration for Wizard framework
3,248 3
Install
npm install @gooonzick/wizard-vue
Latest Version:1.12.0
Vue:3
Last Updated:Oct 7, 2026
Links: GitHub  ·  npm
Maintainer: gooonzick

@gooonzick/wizard-vue

Vue 3 Composition API integration for the Wizard framework.

Features

  • Vue 3 Composable - useWizard() composable with reactive ComputedRef values
  • Organized API - State grouped into logical slices (state, validation, navigation, loading, actions)
  • Navigation History - canGoBack and stepHistory for history-based back navigation
  • Granular Composables - Fine-grained subscriptions with useWizardData(), useWizardNavigation(), etc.
  • v-model Support - useWizardField() for writable computed refs
  • Optional Provider - WizardProvider for sharing state via provide/inject
  • Full Type Safety - TypeScript generics for your data types

Installation

npm install @gooonzick/wizard-vue @gooonzick/wizard-core
# or
pnpm add @gooonzick/wizard-vue @gooonzick/wizard-core
# or
yarn add @gooonzick/wizard-vue @gooonzick/wizard-core

Quick Start

Basic Usage with Composition API

<script setup lang="ts">
import { useWizard } from "@gooonzick/wizard-vue";
import { createLinearWizard } from "@gooonzick/wizard-core";

interface FormData {
  name: string;
  email: string;
  age: number;
}

const definition = createLinearWizard<FormData>({
  id: "my-wizard",
  steps: [
    { id: "personal", title: "Personal Info" },
    { id: "contact", title: "Contact" },
    { id: "review", title: "Review" },
  ],
});

const { state, navigation, loading, actions } = useWizard({
  definition,
  initialData: { name: "", email: "", age: 0 },
});
</script>

<template>
  <div>
    <h2>{{ state.currentStep.value?.title }}</h2>

    <div v-if="state.currentStepId.value === 'personal'">
      <input
        :value="state.data.value.name"
        @input="
          actions.updateField('name', ($event.target as HTMLInputElement).value)
        "
        placeholder="Name"
      />
    </div>

    <div v-else-if="state.currentStepId.value === 'contact'">
      <input
        :value="state.data.value.email"
        @input="
          actions.updateField(
            'email',
            ($event.target as HTMLInputElement).value,
          )
        "
        placeholder="Email"
      />
    </div>

    <div v-else-if="state.currentStepId.value === 'review'">
      <p>Name: {{ state.data.value.name }}</p>
      <p>Email: {{ state.data.value.email }}</p>
    </div>

    <button
      @click="navigation.goPrevious"
      :disabled="!navigation.canGoPrevious.value"
    >
      Previous
    </button>

    <!-- On the last step goNext() completes the wizard; canGoNext is false there. -->
    <button
      @click="navigation.goNext()"
      :disabled="loading.isNavigating.value"
    >
      {{ navigation.isLastStep.value ? "Finish" : "Next" }}
    </button>
  </div>
</template>

Using WizardProvider for Shared State

<!-- App.vue -->
<script setup lang="ts">
import { WizardProvider } from "@gooonzick/wizard-vue";
import { createLinearWizard } from "@gooonzick/wizard-core";
import WizardSteps from "./WizardSteps.vue";
import WizardNavigation from "./WizardNavigation.vue";

const definition = createLinearWizard({
  id: "my-wizard",
  steps: [
    { id: "step1", title: "Step 1" },
    { id: "step2", title: "Step 2" },
  ],
});
</script>

<template>
  <WizardProvider :definition="definition" :initialData="{ name: '' }">
    <WizardSteps />
    <WizardNavigation />
  </WizardProvider>
</template>
<!-- WizardSteps.vue -->
<script setup lang="ts">
import { useWizardData, useWizardActions } from "@gooonzick/wizard-vue";

const { currentStepId, data } = useWizardData();
const { updateField } = useWizardActions();
</script>

<template>
  <div>
    <h2>Current: {{ currentStepId.value }}</h2>
    <input
      :value="data.value.name"
      @input="updateField('name', $event.target.value)"
    />
  </div>
</template>
<!-- WizardNavigation.vue -->
<script setup lang="ts">
import { useWizardLoading, useWizardNavigation } from "@gooonzick/wizard-vue";

const { canGoPrevious, isLastStep, goNext, goPrevious } = useWizardNavigation();
const { isNavigating } = useWizardLoading();
</script>

<template>
  <!-- Top-level refs are auto-unwrapped in the template: no .value here -->
  <div>
    <button @click="goPrevious()" :disabled="!canGoPrevious || isNavigating">
      Previous
    </button>
    <!-- On the last step goNext() completes the wizard; canGoNext is false there. -->
    <button @click="goNext()" :disabled="isNavigating">
      {{ isLastStep ? "Finish" : "Next" }}
    </button>
  </div>
</template>

API Reference

Composables

useWizard(options)

Main composable for wizard state management. Returns organized state slices.

Parameters:

  • definition: WizardDefinition<T> - Wizard configuration
  • initialData: T - Initial form data
  • context?: WizardContext - Optional context for validators/hooks
  • onStateChange?: (state) => void - State change callback
  • onStepEnter?: (stepId, data) => void - Step enter callback
  • onStepLeave?: (stepId, data) => void - Step leave callback
  • onComplete?: (data) => void - Completion callback
  • onCancel?: (data) => void | Promise<void> - Cancel callback
  • onReset?: () => void - Reset callback
  • onError?: (error) => void - Error callback
  • plugins?: WizardPlugin<T>[] - Reference-stable plugins (read once at setup)

Returns:

  • state - Current step, data, stepStatuses, progress (ComputedRefs)
  • validation - Validation state and errors
  • navigation - Navigation state and methods (goPrevious, goTo, …)
  • loading - Async operation states (isValidating, isSubmitting, isNavigating, isLoadingStep)
  • actions - Data mutations, validate / validateAll, submit, reset / cancel, serialize / restore, preloadStep
Granular Composables (require WizardProvider)
  • useWizardData<T>() - State slice only
  • useWizardNavigation() - Navigation slice only
  • useWizardValidation() - Validation slice only
  • useWizardLoading() - Loading slice only
  • useWizardActions<T>() - Actions slice only (validateAll, cancel, …)
  • useWizardField(wizard, field) or useWizardField(field) inside Provider - v-model binding
  • createTypedWizardProvider<T>() - Pre-typed Provider + granular helpers

Components

WizardProvider

Provider component for sharing wizard state via provide/inject.

Props: Same as useWizard options, plus children

TypeScript Support

All composables and components are fully typed with TypeScript generics:

interface MyFormData {
  name: string;
  email: string;
}

const { state, actions } = useWizard<MyFormData>({
  definition,
  initialData: { name: "", email: "" },
});

// TypeScript knows the shape of data
actions.updateField("name", "John"); // ✓ OK
actions.updateField("invalid", "value"); // ✗ Error

License

MIT

Related Packages

@daltonr/pathwrite-vue

Vue 3 adapter for @daltonr/pathwrite-core — composables with reactive refs, and...

3,961 5
vue-form-wizard

A vue based tab/form wizard

790,689 1,098
@anivive/vue3-form-wizard

Vue 3 wizard style json form generator

24,889 18
vue-formless

Vue 3 表单组合式 hooks

648 0
@adbros/vue-validation

Composable for schema-based form validation in Vue 3 using Valibot

6,036 0

Version History

Version Released Vue License
1.12.0 ^3.5.39
1.11.2 ^3.5.39
1.11.1 ^3.5.39
1.11.0 ^3.5.39
1.10.0 ^3.5.39