Use o componente Stepper para exibir uma lista de itens em um stepper.
<script setup lang="ts">
import type { StepperItem } from '@nitro/ui'
const items = ref<StepperItem[]>([
{
title: 'Address',
description: 'Add your address here',
icon: 'i-lucide-house'
},
{
title: 'Shipping',
description: 'Set your preferred shipping method',
icon: 'i-lucide-truck'
},
{
title: 'Checkout',
description: 'Confirm your order'
}
])
</script>
<template>
<NStepper :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { StepperItem } from '@nitro/ui'
const items = ref<StepperItem[]>([
{
title: 'Address',
description: 'Add your address here',
icon: 'i-lucide-house'
},
{
title: 'Shipping',
description: 'Set your preferred shipping method',
icon: 'i-lucide-truck'
},
{
title: 'Checkout',
description: 'Confirm your order'
}
])
</script>
<template>
<NStepper :items="items" />
</template>
Use a prop items como um array de objetos com as seguintes propriedades:
title?: stringdescription?: AvatarPropscontent?: stringicon?: stringvalue?: string | numberdisabled?: booleanslot?: stringclass?: anyui?: { item?: ClassNameValue, container?: ClassNameValue, trigger?: ClassNameValue, indicator?: ClassNameValue, icon?: ClassNameValue, separator?: ClassNameValue, wrapper?: ClassNameValue, title?: ClassNameValue, description?: ClassNameValue }<script setup lang="ts">
import type { StepperItem } from '@nitro/ui'
const items = ref<StepperItem[]>([
{
title: 'Address',
description: 'Add your address here',
icon: 'i-lucide-house'
},
{
title: 'Shipping',
description: 'Set your preferred shipping method',
icon: 'i-lucide-truck'
},
{
title: 'Checkout',
description: 'Confirm your order'
}
])
</script>
<template>
<NStepper :items="items" class="w-full" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { StepperItem } from '@nitro/ui'
const items = ref<StepperItem[]>([
{
title: 'Address',
description: 'Add your address here',
icon: 'i-lucide-house'
},
{
title: 'Shipping',
description: 'Set your preferred shipping method',
icon: 'i-lucide-truck'
},
{
title: 'Checkout',
description: 'Confirm your order'
}
])
</script>
<template>
<NStepper :items="items" class="w-full" />
</template>
Use a prop color para alterar a cor do Stepper.
<script setup lang="ts">
import type { StepperItem } from '@nitro/ui'
const items = ref<StepperItem[]>([
{
title: 'Address',
description: 'Add your address here',
icon: 'i-lucide-house'
},
{
title: 'Shipping',
description: 'Set your preferred shipping method',
icon: 'i-lucide-truck'
},
{
title: 'Checkout',
description: 'Confirm your order'
}
])
</script>
<template>
<NStepper color="neutral" :items="items" class="w-full" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { StepperItem } from '@nitro/ui'
const items = ref<StepperItem[]>([
{
title: 'Address',
description: 'Add your address here',
icon: 'i-lucide-house'
},
{
title: 'Shipping',
description: 'Set your preferred shipping method',
icon: 'i-lucide-truck'
},
{
title: 'Checkout',
description: 'Confirm your order'
}
])
</script>
<template>
<NStepper color="neutral" :items="items" class="w-full" />
</template>
Use a prop size para alterar o tamanho do Stepper.
<script setup lang="ts">
import type { StepperItem } from '@nitro/ui'
const items = ref<StepperItem[]>([
{
title: 'Address',
description: 'Add your address here',
icon: 'i-lucide-house'
},
{
title: 'Shipping',
description: 'Set your preferred shipping method',
icon: 'i-lucide-truck'
},
{
title: 'Checkout',
description: 'Confirm your order'
}
])
</script>
<template>
<NStepper size="xl" :items="items" class="w-full" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { StepperItem } from '@nitro/ui'
const items = ref<StepperItem[]>([
{
title: 'Address',
description: 'Add your address here',
icon: 'i-lucide-house'
},
{
title: 'Shipping',
description: 'Set your preferred shipping method',
icon: 'i-lucide-truck'
},
{
title: 'Checkout',
description: 'Confirm your order'
}
])
</script>
<template>
<NStepper size="xl" :items="items" class="w-full" />
</template>
Use a prop orientation para alterar a orientação do Stepper. O padrão é horizontal.
<script setup lang="ts">
import type { StepperItem } from '@nitro/ui'
const items = ref<StepperItem[]>([
{
title: 'Address',
description: 'Add your address here',
icon: 'i-lucide-house'
},
{
title: 'Shipping',
description: 'Set your preferred shipping method',
icon: 'i-lucide-truck'
},
{
title: 'Checkout',
description: 'Confirm your order'
}
])
</script>
<template>
<NStepper orientation="vertical" :items="items" class="w-full" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { StepperItem } from '@nitro/ui'
const items = ref<StepperItem[]>([
{
title: 'Address',
description: 'Add your address here',
icon: 'i-lucide-house'
},
{
title: 'Shipping',
description: 'Set your preferred shipping method',
icon: 'i-lucide-truck'
},
{
title: 'Checkout',
description: 'Confirm your order'
}
])
</script>
<template>
<NStepper orientation="vertical" :items="items" class="w-full" />
</template>
Use a prop disabled para desabilitar a navegação pelas etapas.
<script setup lang="ts">
import type { StepperItem } from '@nitro/ui'
const items = ref<StepperItem[]>([
{
title: 'Address',
description: 'Add your address here',
icon: 'i-lucide-house'
},
{
title: 'Shipping',
description: 'Set your preferred shipping method',
icon: 'i-lucide-truck'
},
{
title: 'Checkout',
description: 'Confirm your order'
}
])
</script>
<template>
<NStepper disabled :items="items" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { StepperItem } from '@nitro/ui'
const items = ref<StepperItem[]>([
{
title: 'Address',
description: 'Add your address here',
icon: 'i-lucide-house'
},
{
title: 'Shipping',
description: 'Set your preferred shipping method',
icon: 'i-lucide-truck'
},
{
title: 'Checkout',
description: 'Confirm your order'
}
])
</script>
<template>
<NStepper disabled :items="items" />
</template>
Você pode adicionar controles adicionais para o stepper usando botões.
Você pode controlar o item ativo usando a prop default-value ou a diretiva v-model com o value do item. Se nenhum value for fornecido, o padrão é o índice.
value-key para alterar a chave usada para corresponder os itens quando um v-model ou default-value é fornecido.Use o slot #content para personalizar o conteúdo de cada item.
Use a propriedade slot para personalizar um item específico.
Você terá acesso aos seguintes slots:
#{{ item.slot }}| Prop | Default | Type |
|---|---|---|
as | 'div' | anyThe element or component this component should render as. |
items | T[] | |
size | 'md' | "xs" | "sm" | "md" | "lg" | "xl" |
color | 'primary' | "primary" | "secondary" | "accent" | "success" | "info" | "warning" | "error" | "neutral" |
orientation | 'horizontal' | "horizontal" | "vertical"The orientation of the stepper. |
valueKey | 'value' | keyof Extract<NestedItem<T>, object> & string | DotPathKeys<Extract<NestedItem<T>, object>>The key used to get the value from the item. |
defaultValue | string | numberThe value of the step that should be active when initially rendered. Use when you do not need to control the state of the steps. | |
disabled | boolean | |
linear | true | boolean Whether or not the steps must be completed in order. |
modelValue | string | number | |
ui | { root?: SlotClass; header?: SlotClass; item?: SlotClass; container?: SlotClass; trigger?: SlotClass; indicator?: SlotClass; icon?: SlotClass; separator?: SlotClass; wrapper?: SlotClass; title?: SlotClass; description?: SlotClass; content?: SlotClass; } |
| Slot | Type |
|---|---|
indicator | { item: T; ui: object; } |
wrapper | { item: T; } |
title | { item: T; } |
description | { item: T; } |
content | { item: T; } |
| Event | Type |
|---|---|
next | [value: T] |
prev | [value: T] |
update:modelValue | [value: string | number | undefined] |
Você pode acessar a instância tipada do componente usando useTemplateRef.
<script setup lang="ts">
const stepper = useTemplateRef('stepper')
</script>
<template>
<NStepper ref="stepper" />
</template>
Isso dará a você acesso ao seguinte:
| Name | Type |
|---|---|
next | () => void |
prev | () => void |
hasNext | Ref<boolean> |
hasPrev | Ref<boolean> |
export default defineAppConfig({
ui: {
stepper: {
slots: {
root: 'flex gap-4',
header: 'flex',
item: 'group text-center relative w-full',
container: 'relative',
trigger: 'rounded-full font-medium text-center align-middle flex items-center justify-center font-semibold group-data-[state=completed]:text-inverted group-data-[state=active]:text-inverted text-muted bg-elevated focus-visible:outline-2 focus-visible:outline-offset-2',
indicator: 'flex items-center justify-center size-full',
icon: 'shrink-0',
separator: 'absolute rounded-full group-data-[disabled]:opacity-75 bg-accented',
wrapper: '',
title: 'font-medium text-default',
description: 'text-muted text-wrap',
content: 'size-full'
},
variants: {
orientation: {
horizontal: {
root: 'flex-col',
container: 'flex justify-center',
separator: 'top-[calc(50%-2px)] h-0.5',
wrapper: 'mt-1'
},
vertical: {
header: 'flex-col gap-4',
item: 'flex text-start',
separator: 'start-[calc(50%-1px)] -bottom-[10px] w-0.5'
}
},
size: {
xs: {
trigger: 'size-6 text-xs',
icon: 'size-3',
title: 'text-xs',
description: 'text-xs',
wrapper: 'mt-1.5'
},
sm: {
trigger: 'size-8 text-sm',
icon: 'size-4',
title: 'text-xs',
description: 'text-xs',
wrapper: 'mt-2'
},
md: {
trigger: 'size-10 text-base',
icon: 'size-5',
title: 'text-sm',
description: 'text-sm',
wrapper: 'mt-2.5'
},
lg: {
trigger: 'size-12 text-lg',
icon: 'size-6',
title: 'text-base',
description: 'text-base',
wrapper: 'mt-3'
},
xl: {
trigger: 'size-14 text-xl',
icon: 'size-7',
title: 'text-lg',
description: 'text-lg',
wrapper: 'mt-3.5'
}
},
color: {
primary: {
trigger: 'group-data-[state=completed]:bg-primary group-data-[state=active]:bg-primary focus-visible:outline-primary',
separator: 'group-data-[state=completed]:bg-primary'
},
secondary: {
trigger: 'group-data-[state=completed]:bg-secondary group-data-[state=active]:bg-secondary focus-visible:outline-secondary',
separator: 'group-data-[state=completed]:bg-secondary'
},
accent: {
trigger: 'group-data-[state=completed]:bg-accent group-data-[state=active]:bg-accent focus-visible:outline-accent',
separator: 'group-data-[state=completed]:bg-accent'
},
success: {
trigger: 'group-data-[state=completed]:bg-success group-data-[state=active]:bg-success focus-visible:outline-success',
separator: 'group-data-[state=completed]:bg-success'
},
info: {
trigger: 'group-data-[state=completed]:bg-info group-data-[state=active]:bg-info focus-visible:outline-info',
separator: 'group-data-[state=completed]:bg-info'
},
warning: {
trigger: 'group-data-[state=completed]:bg-warning group-data-[state=active]:bg-warning focus-visible:outline-warning',
separator: 'group-data-[state=completed]:bg-warning'
},
error: {
trigger: 'group-data-[state=completed]:bg-error group-data-[state=active]:bg-error focus-visible:outline-error',
separator: 'group-data-[state=completed]:bg-error'
},
neutral: {
trigger: 'group-data-[state=completed]:bg-inverted group-data-[state=active]:bg-inverted focus-visible:outline-inverted',
separator: 'group-data-[state=completed]:bg-inverted'
}
}
},
compoundVariants: [
{
orientation: 'horizontal',
size: 'xs',
class: {
separator: 'start-[calc(50%+16px)] end-[calc(-50%+16px)]'
}
},
{
orientation: 'horizontal',
size: 'sm',
class: {
separator: 'start-[calc(50%+20px)] end-[calc(-50%+20px)]'
}
},
{
orientation: 'horizontal',
size: 'md',
class: {
separator: 'start-[calc(50%+28px)] end-[calc(-50%+28px)]'
}
},
{
orientation: 'horizontal',
size: 'lg',
class: {
separator: 'start-[calc(50%+32px)] end-[calc(-50%+32px)]'
}
},
{
orientation: 'horizontal',
size: 'xl',
class: {
separator: 'start-[calc(50%+36px)] end-[calc(-50%+36px)]'
}
},
{
orientation: 'vertical',
size: 'xs',
class: {
separator: 'top-[30px]',
item: 'gap-1.5'
}
},
{
orientation: 'vertical',
size: 'sm',
class: {
separator: 'top-[38px]',
item: 'gap-2'
}
},
{
orientation: 'vertical',
size: 'md',
class: {
separator: 'top-[46px]',
item: 'gap-2.5'
}
},
{
orientation: 'vertical',
size: 'lg',
class: {
separator: 'top-[54px]',
item: 'gap-3'
}
},
{
orientation: 'vertical',
size: 'xl',
class: {
separator: 'top-[62px]',
item: 'gap-3.5'
}
}
],
defaultVariants: {
size: 'md',
color: 'primary'
}
}
}
})
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nitro/ui/vite'
export default defineConfig({
plugins: [
vue(),
ui({
ui: {
stepper: {
slots: {
root: 'flex gap-4',
header: 'flex',
item: 'group text-center relative w-full',
container: 'relative',
trigger: 'rounded-full font-medium text-center align-middle flex items-center justify-center font-semibold group-data-[state=completed]:text-inverted group-data-[state=active]:text-inverted text-muted bg-elevated focus-visible:outline-2 focus-visible:outline-offset-2',
indicator: 'flex items-center justify-center size-full',
icon: 'shrink-0',
separator: 'absolute rounded-full group-data-[disabled]:opacity-75 bg-accented',
wrapper: '',
title: 'font-medium text-default',
description: 'text-muted text-wrap',
content: 'size-full'
},
variants: {
orientation: {
horizontal: {
root: 'flex-col',
container: 'flex justify-center',
separator: 'top-[calc(50%-2px)] h-0.5',
wrapper: 'mt-1'
},
vertical: {
header: 'flex-col gap-4',
item: 'flex text-start',
separator: 'start-[calc(50%-1px)] -bottom-[10px] w-0.5'
}
},
size: {
xs: {
trigger: 'size-6 text-xs',
icon: 'size-3',
title: 'text-xs',
description: 'text-xs',
wrapper: 'mt-1.5'
},
sm: {
trigger: 'size-8 text-sm',
icon: 'size-4',
title: 'text-xs',
description: 'text-xs',
wrapper: 'mt-2'
},
md: {
trigger: 'size-10 text-base',
icon: 'size-5',
title: 'text-sm',
description: 'text-sm',
wrapper: 'mt-2.5'
},
lg: {
trigger: 'size-12 text-lg',
icon: 'size-6',
title: 'text-base',
description: 'text-base',
wrapper: 'mt-3'
},
xl: {
trigger: 'size-14 text-xl',
icon: 'size-7',
title: 'text-lg',
description: 'text-lg',
wrapper: 'mt-3.5'
}
},
color: {
primary: {
trigger: 'group-data-[state=completed]:bg-primary group-data-[state=active]:bg-primary focus-visible:outline-primary',
separator: 'group-data-[state=completed]:bg-primary'
},
secondary: {
trigger: 'group-data-[state=completed]:bg-secondary group-data-[state=active]:bg-secondary focus-visible:outline-secondary',
separator: 'group-data-[state=completed]:bg-secondary'
},
accent: {
trigger: 'group-data-[state=completed]:bg-accent group-data-[state=active]:bg-accent focus-visible:outline-accent',
separator: 'group-data-[state=completed]:bg-accent'
},
success: {
trigger: 'group-data-[state=completed]:bg-success group-data-[state=active]:bg-success focus-visible:outline-success',
separator: 'group-data-[state=completed]:bg-success'
},
info: {
trigger: 'group-data-[state=completed]:bg-info group-data-[state=active]:bg-info focus-visible:outline-info',
separator: 'group-data-[state=completed]:bg-info'
},
warning: {
trigger: 'group-data-[state=completed]:bg-warning group-data-[state=active]:bg-warning focus-visible:outline-warning',
separator: 'group-data-[state=completed]:bg-warning'
},
error: {
trigger: 'group-data-[state=completed]:bg-error group-data-[state=active]:bg-error focus-visible:outline-error',
separator: 'group-data-[state=completed]:bg-error'
},
neutral: {
trigger: 'group-data-[state=completed]:bg-inverted group-data-[state=active]:bg-inverted focus-visible:outline-inverted',
separator: 'group-data-[state=completed]:bg-inverted'
}
}
},
compoundVariants: [
{
orientation: 'horizontal',
size: 'xs',
class: {
separator: 'start-[calc(50%+16px)] end-[calc(-50%+16px)]'
}
},
{
orientation: 'horizontal',
size: 'sm',
class: {
separator: 'start-[calc(50%+20px)] end-[calc(-50%+20px)]'
}
},
{
orientation: 'horizontal',
size: 'md',
class: {
separator: 'start-[calc(50%+28px)] end-[calc(-50%+28px)]'
}
},
{
orientation: 'horizontal',
size: 'lg',
class: {
separator: 'start-[calc(50%+32px)] end-[calc(-50%+32px)]'
}
},
{
orientation: 'horizontal',
size: 'xl',
class: {
separator: 'start-[calc(50%+36px)] end-[calc(-50%+36px)]'
}
},
{
orientation: 'vertical',
size: 'xs',
class: {
separator: 'top-[30px]',
item: 'gap-1.5'
}
},
{
orientation: 'vertical',
size: 'sm',
class: {
separator: 'top-[38px]',
item: 'gap-2'
}
},
{
orientation: 'vertical',
size: 'md',
class: {
separator: 'top-[46px]',
item: 'gap-2.5'
}
},
{
orientation: 'vertical',
size: 'lg',
class: {
separator: 'top-[54px]',
item: 'gap-3'
}
},
{
orientation: 'vertical',
size: 'xl',
class: {
separator: 'top-[62px]',
item: 'gap-3.5'
}
}
],
defaultVariants: {
size: 'md',
color: 'primary'
}
}
}
})
]
})