Overview
nuxtUIMultiStep and nuxtUIStep wrap @formkit/addons' createMultiStepPlugin to build wizard-style forms. nuxtUIMultiStep renders a Nuxt UI UTabs tab strip and owns navigation; each nuxtUIStep child renders one step's fields plus Nuxt UI-styled previous/next buttons.
Unlike most other input components, both require the createMultiStepPlugin() plugin itself to be registered in your plugins array - the input definitions alone aren't enough, since the plugin is what adds each step's navigation methods (next, previous, goTo) and validation-gating logic.
Setup
// formkit.config.ts
import type { DefaultConfigOptions } from '@formkit/vue'
import { nuxtUIInputs } from '@sfxcode/nuxt-ui-formkit/definitions'
import { createMultiStepPlugin } from '@sfxcode/nuxt-ui-formkit/plugins'
const config: DefaultConfigOptions = {
inputs: { ...nuxtUIInputs },
plugins: [
createMultiStepPlugin(),
],
}
export default config2
3
4
5
6
7
8
9
10
11
12
13
Basic Usage
<template>
<FormKit type="form" @submit="handleSubmit">
<FormKit type="nuxtUIMultiStep" name="wizard" :allow-incomplete="false">
<FormKit type="nuxtUIStep" name="account" label="Account">
<FormKit
type="nuxtUIInput"
name="email"
input-type="email"
label="Email"
validation="required|email"
/>
</FormKit>
<FormKit type="nuxtUIStep" name="profile" label="Profile">
<FormKit
type="nuxtUIInput"
name="displayName"
label="Display Name"
validation="required"
/>
</FormKit>
</FormKit>
</FormKit>
</template>
<script setup lang="ts">
const handleSubmit = (data: any) => {
console.log('Wizard data:', data.wizard)
}
</script>2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Schema-Based Multi-Step
const schema = [
{
$formkit: 'nuxtUIMultiStep',
name: 'wizard',
allowIncomplete: false,
children: [
{
$formkit: 'nuxtUIStep',
name: 'account',
label: 'Account',
children: [
{ $formkit: 'nuxtUIInput', name: 'email', label: 'Email', validation: 'required|email' },
],
},
{
$formkit: 'nuxtUIStep',
name: 'profile',
label: 'Profile',
children: [
{ $formkit: 'nuxtUIInput', name: 'displayName', label: 'Display Name', validation: 'required' },
],
},
],
},
]2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Props
nuxtUIMultiStep
- allowIncomplete - When
false, advancing past a step whose fields fail validation is blocked. Defaults totrue(the addon's own default), so set this explicitly to get validation gating. - tabStyle -
'tab'(the only style this wrapper styles withUTabs;'progress'is a supported addon value but renders unstyled). - hideProgressLabels - Forwarded to the addon; has no visible effect on the
UTabstab strip this wrapper renders. - validStepIcon - Icon name shown as a tab badge once a visited step becomes valid (default:
i-lucide-check). - beforeStepChange - Async guard called before navigating; return
falseto cancel the transition. See@formkit/addons' docs for the callback signature. - ui - Forwarded to the underlying
UTabscomponent for style overrides.
nuxtUIStep
- previousLabel / nextLabel - Override the previous/next button text (defaults: "Previous"/"Next").
- previousAttrs / nextAttrs - Extra props/attrs forwarded to the previous/next
UButton. - beforeStepChange - Per-step override of the multi-step's own guard.
- validStepIcon - Per-step override of the tab badge icon.
- ui - Forwarded to the previous/next
UButtons for style overrides. - stepActionsClass - Class for the div wrapping the previous/next buttons (default:
'flex gap-2 pt-2'; always merged with theformkit-step-actionsbase class).
Navigating Programmatically
The addon plugin extends the multi-step's FormKitNode with next(), previous(), and goTo(step) methods:
import { getNode } from '@formkit/core'
const wizard = getNode('wizard')
wizard?.goTo('profile') // by step name
wizard?.goTo(1) // by index
wizard?.next()
wizard?.previous()2
3
4
5
6
7
Validation Gating
With allow-incomplete="false", clicking "Next" (or a tab, or calling goTo/next programmatically) on a step with invalid fields triggers that step's validation messages and blocks the transition until the fields validate. Leave allowIncomplete unset (or true) to let users move freely between steps regardless of validation state.
With allow-incomplete="false", the current step's own "Next" button and any not-yet-visited tab are also proactively disabled while the current step is invalid, rather than left clickable-but-inert — both re-enable automatically once the current step's fields validate. Already-visited tabs (including the active one) always stay enabled, since moving backward is never gated.