Steps
A step indicator component for multi-step workflows. Supports horizontal and vertical layouts, icons, descriptions, error states, clickable navigation, multiple sizes, and full CSS customization.
Basic
<script setup>
import { ref } from 'vue'
import { VxSteps } from 'veloxui'
const current = ref(1)
const items = [
{ key: 'account', title: 'Account' },
{ key: 'profile', title: 'Profile' },
{ key: 'review', title: 'Review' },
{ key: 'done', title: 'Done' },
]
</script>
<template>
<VxSteps :items="items" :current="current" />
</template>With Descriptions
<VxSteps :items="[
{ key: 'account', title: 'Account', description: 'Create your account credentials' },
{ key: 'profile', title: 'Profile', description: 'Fill in your personal details' },
{ key: 'review', title: 'Review', description: 'Verify all information' },
{ key: 'done', title: 'Done', description: 'Setup complete' },
]" :current="1" />With Icons
<VxSteps :items="[
{ key: 'account', title: 'Account', icon: 'user' },
{ key: 'settings', title: 'Settings', icon: 'settings' },
{ key: 'upload', title: 'Upload', icon: 'upload' },
{ key: 'done', title: 'Complete', icon: 'check' },
]" :current="2" />Error State
Set error: true on a step item to show it in an error state.
<VxSteps :items="[
{ key: 'account', title: 'Account' },
{ key: 'verify', title: 'Verification', error: true },
{ key: 'done', title: 'Done' },
]" :current="1" />Clickable
Set clickable to allow clicking on any step. Use v-model:current for two-way binding.
<VxSteps v-model:current="current" :items="items" clickable />Vertical
<script setup>
import { ref } from 'vue'
import { VxSteps } from 'veloxui'
const current = ref(1)
const items = [
{ key: 'order', title: 'Order Placed', description: 'Your order has been submitted' },
{ key: 'processing', title: 'Processing', description: 'We are preparing your order' },
{ key: 'shipped', title: 'Shipped', description: 'Package is on its way' },
{ key: 'delivered', title: 'Delivered', description: 'Package has arrived' },
]
</script>
<template>
<VxSteps :items="items" :current="current" direction="vertical" />
</template>Sizes
Three sizes: sm, md (default), and lg.
<VxSteps :items="items" :current="2" size="sm" />
<VxSteps :items="items" :current="2" size="md" />
<VxSteps :items="items" :current="2" size="lg" />Square Variant
Use variant="square" for rounded-square indicators instead of circles.
<VxSteps :items="items" :current="1" variant="square" clickable />
<VxSteps :items="items" :current="2" variant="square" direction="vertical" />Custom Dot Size & Line Width
Use dot-size and line-width props to override the size preset values.
<VxSteps :items="items" :current="1" :dot-size="40" :line-width="2" />
<VxSteps :items="items" :current="1" :dot-size="20" :line-width="2" />Custom Colors (CSS Variables)
Override any visual aspect via CSS custom properties on a wrapper class.
<template>
<div class="steps-green-theme">
<VxSteps :items="items" :current="1" clickable />
</div>
</template>
<style>
.steps-green-theme .vx-steps {
--vx-steps-active-bg: #16a34a;
--vx-steps-active-border: #16a34a;
--vx-steps-active-color: #fff;
--vx-steps-active-shadow: 0 0 0 3px rgba(22, 163, 74, 0.16);
--vx-steps-completed-bg: #16a34a;
--vx-steps-completed-border: #16a34a;
--vx-steps-completed-color: #fff;
--vx-steps-line-done-color: #16a34a;
}
</style>Custom Slots
Use slots to fully customize titles, descriptions, icons, and add extra content per step.
<VxSteps :items="items" :current="current" clickable direction="vertical">
<!-- Custom title for all steps -->
<template #title="{ item, status }">
<span :style="{ fontWeight: status === 'active' ? 700 : 400 }">
{{ item.title }}
<VxTag v-if="status === 'active'" size="sm">Current</VxTag>
</span>
</template>
<!-- Extra content only for the 'review' step -->
<template #content-review="{ status }">
<div v-if="status === 'active'" style="padding: 12px; background: var(--muted); border-radius: 8px;">
Please review all your information before proceeding.
</div>
</template>
</VxSteps>Content Panel
Use panel-{key} slots to render step-specific content below the steps bar. The active step's panel is shown automatically.
<script setup>
import { ref } from 'vue'
import { VxSteps, VxInput, VxButton } from 'veloxui'
const current = ref(0)
const items = [
{ key: 'account', title: 'Account' },
{ key: 'profile', title: 'Profile' },
{ key: 'confirm', title: 'Confirm' },
]
function next() {
if (current.value < items.length - 1) current.value++
}
function prev() {
if (current.value > 0) current.value--
}
</script>
<template>
<VxSteps :items="items" :current="current" clickable>
<template #panel-account>
<div style="padding: 20px; border: 1px solid var(--border); border-radius: 10px;">
<VxInput placeholder="Email address" />
<VxInput placeholder="Password" type="password" />
<VxButton size="sm" @click="next">Next</VxButton>
</div>
</template>
<template #panel-profile>
<div style="padding: 20px; border: 1px solid var(--border); border-radius: 10px;">
<VxInput placeholder="Full name" />
<VxButton variant="outline" size="sm" @click="prev">Back</VxButton>
<VxButton size="sm" @click="next">Next</VxButton>
</div>
</template>
<template #panel-confirm>
<div style="text-align: center;">All done!</div>
</template>
</VxSteps>
</template>Vertical Content Panel
The content panel works with vertical direction too — it renders beside the steps.
<VxSteps :items="items" :current="current" direction="vertical" clickable>
<template #panel-info>
<!-- Your form content here -->
</template>
<template #panel-address>
<!-- Address form -->
</template>
<template #panel-payment>
<!-- Payment form -->
</template>
</VxSteps>Simple Wizard
A minimal wizard with just Next / Back buttons (no content panel).
<script setup>
import { ref } from 'vue'
import { VxSteps, VxButton } from 'veloxui'
const current = ref(0)
const items = [
{ key: 'plan', title: 'Choose Plan' },
{ key: 'billing', title: 'Billing' },
{ key: 'confirm', title: 'Confirm' },
]
function next() {
if (current.value < items.length - 1) current.value++
}
function prev() {
if (current.value > 0) current.value--
}
</script>
<template>
<VxSteps :items="items" :current="current" />
<div style="margin-top: 20px; display: flex; gap: 8px; justify-content: flex-end;">
<VxButton variant="outline" size="sm" :disabled="current === 0" @click="prev">Back</VxButton>
<VxButton size="sm" @click="next" :disabled="current === items.length - 1">Next</VxButton>
</div>
</template>API
VxSteps Props
| Prop | Type | Default | Description |
|---|---|---|---|
items | StepItem[] | [] | Step items |
current | number | 0 | Active step index (zero-based) |
direction | 'horizontal' | 'vertical' | 'horizontal' | Layout direction |
size | 'sm' | 'md' | 'lg' | 'md' | Step indicator size |
variant | 'circle' | 'square' | 'circle' | Indicator shape |
clickable | boolean | false | Allow clicking steps to navigate |
dot-size | number | string | — | Override indicator size (e.g. 40 or '40px') |
line-width | number | string | — | Override line thickness (e.g. 2 or '2px') |
root-class | string | string[] | object | — | Class on root |
StepItem
| Property | Type | Required | Description |
|---|---|---|---|
key | string | Yes | Unique identifier |
title | string | Yes | Step title |
description | string | No | Step description text |
icon | string | Component | No | Custom icon (replaces number) |
disabled | boolean | No | Disable this step |
error | boolean | No | Show error state |
Slots
| Slot | Props | Description |
|---|---|---|
icon | { item, status, index } | Custom indicator for all steps |
icon-{key} | { item, status, index } | Custom indicator for a specific step |
title | { item, status, index } | Custom title for all steps |
title-{key} | { item, status, index } | Custom title for a specific step |
description | { item, status, index } | Custom description for all steps |
description-{key} | { item, status, index } | Custom description for a specific step |
content-{key} | { item, status, index } | Extra content area below a specific step's text |
line | { index, status, done } | Custom line connector between steps |
panel | { item, status, index } | Default content panel for all steps |
panel-{key} | { item, status, index } | Content panel for a specific step (shown when active) |
Events
| Event | Payload | Description |
|---|---|---|
update:current | (index: number) | Step changed (clickable mode) |
click | (index, item) | Step clicked |
CSS Custom Properties
Override these on the .vx-steps element or a parent wrapper to customize colors, sizing, and spacing.
| Variable | Default | Description |
|---|---|---|
--vx-steps-dot-size | Size preset | Indicator width/height |
--vx-steps-dot-radius | 50% / 8px | Indicator border-radius |
--vx-steps-dot-font-size | Size preset | Number font-size in dot |
--vx-steps-dot-font-weight | 600 | Number font-weight in dot |
--vx-steps-dot-bg | var(--background) | Upcoming dot background |
--vx-steps-dot-border | var(--border) | Upcoming dot border |
--vx-steps-dot-color | var(--muted-foreground) | Upcoming dot text color |
--vx-steps-active-bg | var(--primary) | Active dot background |
--vx-steps-active-border | var(--primary) | Active dot border |
--vx-steps-active-color | var(--primary-foreground) | Active dot text color |
--vx-steps-active-shadow | ring glow | Active dot box-shadow |
--vx-steps-completed-bg | var(--primary) | Completed dot background |
--vx-steps-completed-border | var(--primary) | Completed dot border |
--vx-steps-completed-color | var(--primary-foreground) | Completed dot text color |
--vx-steps-error-bg | var(--background) | Error dot background |
--vx-steps-error-border | var(--destructive) | Error dot border |
--vx-steps-error-color | var(--destructive) | Error dot text color |
--vx-steps-line-color | var(--border) | Incomplete line color |
--vx-steps-line-done-color | var(--primary) | Completed line color |
--vx-steps-line-width | 1px | Line thickness |
--vx-steps-title-size | Size preset | Title font-size |
--vx-steps-title-weight | 500 | Title font-weight |
--vx-steps-title-color | var(--foreground) | Title color |
--vx-steps-title-upcoming-color | var(--muted-foreground) | Upcoming title color |
--vx-steps-title-error-color | var(--destructive) | Error title color |
--vx-steps-desc-size | Size preset | Description font-size |
--vx-steps-desc-color | var(--muted-foreground) | Description color |
--vx-steps-text-gap | 8px | Gap between indicator and text (horizontal) |
--vx-steps-line-gap | 24px | Vertical spacing between steps |
--vx-steps-panel-gap | 24px | Gap between steps bar and content panel |
--vx-steps-panel-padding | 0 | Content panel padding |