Skip to content
Kappa
Steps
@dicehub/kappav0.4.2

Steps

Shows progress through an ordered process and controls movement between its stages.

<script setup>
import { Steps } from "@dicehub/kappa/components/steps";

const steps = ["Configuration", "Review", "Run"];
</script>

<template>
  <Steps.Root :count="steps.length" :default-step="0">
    <Steps.Progress />
    <Steps.List aria-label="Case setup progress">
      <Steps.Item v-for="(label, index) in steps" :key="label" :index="index">
        <Steps.Trigger>
          <Steps.Indicator v-slot="{ completed }">
            {{ completed ? "✓" : index + 1 }}
          </Steps.Indicator>
          <span>{{ label }}</span>
        </Steps.Trigger>
        <Steps.Separator v-if="index < steps.length - 1" />
      </Steps.Item>
    </Steps.List>

    <Steps.Content v-for="(label, index) in steps" :key="label" :index="index">
      {{ label }} settings.
    </Steps.Content>
    <Steps.CompletedContent aria-label="Case setup complete">
      Ready to run.
    </Steps.CompletedContent>

    <Steps.PrevTrigger>Back</Steps.PrevTrigger>
    <Steps.Context v-slot="{ isCompleted, resetStep }">
      <button v-if="isCompleted" type="button" @click="resetStep">Reset</button>
      <Steps.NextTrigger v-else>Next</Steps.NextTrigger>
    </Steps.Context>
  </Steps.Root>
</template>

Installation

Barrel

import { Steps } from "@dicehub/kappa";

Granular

import { Steps } from "@dicehub/kappa/components/steps";

Usage

Give each item and content panel the same zero-based index. Set count to the number of items. The completion state starts when step equals count.

<script setup>
import { Steps } from "@dicehub/kappa/components/steps";

const steps = ["Configuration", "Review", "Run"];
</script>

<template>
  <Steps.Root :count="steps.length" :default-step="0">
    <Steps.Progress />
    <Steps.List aria-label="Case setup progress">
      <Steps.Item v-for="(label, index) in steps" :key="label" :index="index">
        <Steps.Trigger>
          <Steps.Indicator v-slot="{ completed }">
            {{ completed ? "✓" : index + 1 }}
          </Steps.Indicator>
          <span>{{ label }}</span>
        </Steps.Trigger>
        <Steps.Separator v-if="index < steps.length - 1" />
      </Steps.Item>
    </Steps.List>

    <Steps.Content v-for="(label, index) in steps" :key="label" :index="index">
      {{ label }} settings.
    </Steps.Content>
    <Steps.CompletedContent aria-label="Case setup complete">
      Ready to run.
    </Steps.CompletedContent>

    <Steps.PrevTrigger>Back</Steps.PrevTrigger>
    <Steps.Context v-slot="{ isCompleted, resetStep }">
      <button v-if="isCompleted" type="button" @click="resetStep">Reset</button>
      <Steps.NextTrigger v-else>Next</Steps.NextTrigger>
    </Steps.Context>
  </Steps.Root>
</template>

Composition

Typical part hierarchy
Steps.Root
├── Steps.Progress (optional)
├── Steps.List
│   └── Steps.Item (one per index)
│       ├── Steps.Trigger
│       │   └── Steps.Indicator
│       └── Steps.Separator (except last item)
├── Steps.Content (one per index)
├── Steps.CompletedContent
├── Steps.PrevTrigger
└── Steps.NextTrigger

Place each trigger, indicator, and separator inside its item. Every enabled item needs a matching content panel. The indicator slot exposes its item state for custom complete and current markers.

<script setup>
import {
  StepsCompletedContent,
  StepsContent,
  StepsIndicator,
  StepsItem,
  StepsList,
  StepsRoot,
  StepsSeparator,
  StepsTrigger,
} from "@dicehub/kappa/components/steps";
</script>

<template>
  <StepsRoot :count="2" :default-step="0">
    <StepsList aria-label="Import progress">
      <StepsItem :index="0">
        <StepsTrigger>
          <StepsIndicator as-child><span>1</span></StepsIndicator>
          Upload
        </StepsTrigger>
        <StepsSeparator />
      </StepsItem>
      <StepsItem :index="1">
        <StepsTrigger><StepsIndicator>2</StepsIndicator>Map fields</StepsTrigger>
      </StepsItem>
    </StepsList>
    <StepsContent :index="0">Choose a case archive.</StepsContent>
    <StepsContent :index="1">Map the imported fields.</StepsContent>
    <StepsCompletedContent aria-label="Import complete">Import complete.</StepsCompletedContent>
  </StepsRoot>
</template>

Examples

Basic

Connect indexed items and panels, then use the built-in navigation triggers.

<script setup>
import { Steps } from "@dicehub/kappa/components/steps";

const steps = ["Configuration", "Review", "Run"];
</script>

<template>
  <Steps.Root :count="steps.length" :default-step="0">
    <Steps.Progress />
    <Steps.List aria-label="Case setup progress">
      <Steps.Item v-for="(label, index) in steps" :key="label" :index="index">
        <Steps.Trigger>
          <Steps.Indicator v-slot="{ completed }">
            {{ completed ? "✓" : index + 1 }}
          </Steps.Indicator>
          <span>{{ label }}</span>
        </Steps.Trigger>
        <Steps.Separator v-if="index < steps.length - 1" />
      </Steps.Item>
    </Steps.List>

    <Steps.Content v-for="(label, index) in steps" :key="label" :index="index">
      {{ label }} settings.
    </Steps.Content>
    <Steps.CompletedContent aria-label="Case setup complete">
      Ready to run.
    </Steps.CompletedContent>

    <Steps.PrevTrigger>Back</Steps.PrevTrigger>
    <Steps.Context v-slot="{ isCompleted, resetStep }">
      <button v-if="isCompleted" type="button" @click="resetStep">Reset</button>
      <Steps.NextTrigger v-else>Next</Steps.NextTrigger>
    </Steps.Context>
  </Steps.Root>
</template>

Vertical

Use a vertical list when labels need more room or the flow sits beside its panel.

<Steps.Root :count="3" :default-step="1" orientation="vertical">
  <Steps.List aria-label="Deployment progress">
    <Steps.Item v-for="(label, index) in steps" :key="label" :index="index">
      <Steps.Trigger>
        <Steps.Indicator>{{ index + 1 }}</Steps.Indicator>
        <span>{{ label }}</span>
      </Steps.Trigger>
      <Steps.Separator v-if="index < steps.length - 1" />
    </Steps.Item>
  </Steps.List>
  <Steps.Content v-for="(label, index) in steps" :key="label" :index="index">
    {{ label }} settings.
  </Steps.Content>
  <Steps.CompletedContent aria-label="Deployment complete">Complete.</Steps.CompletedContent>
</Steps.Root>

Sizes

Use the small size for dense workflows and the base size for standard forms.

<Steps.Root :count="3" :default-step="1">
  <Steps.List size="base" aria-label="Base steps">...</Steps.List>
</Steps.Root>

<Steps.Root :count="3" :default-step="1">
  <Steps.List size="sm" aria-label="Small steps">...</Steps.List>
</Steps.Root>

Controlled

Bind step when the application must reset or coordinate the active stage.

<script setup>
import { ref } from "vue";
import { Steps } from "@dicehub/kappa/components/steps";

const step = ref(1);
</script>

<template>
  <Steps.Root v-model:step="step" :count="3">
    <Steps.List aria-label="Controlled progress">...</Steps.List>
    <Steps.Content :index="0">Configuration</Steps.Content>
    <Steps.Content :index="1">Review</Steps.Content>
    <Steps.Content :index="2">Run</Steps.Content>
    <Steps.CompletedContent aria-label="Process complete">Complete.</Steps.CompletedContent>
    <button type="button" @click="step = 0">Reset</button>
    <Steps.NextTrigger>Next</Steps.NextTrigger>
  </Steps.Root>
  <output aria-live="polite">Step: {{ step }}</output>
</template>

Correspondence

ReferenceCorresponding componentRole in Kappa
KumoNoneNo corresponding component.
Ark UIStepsBehavior, state, and accessibility base.
shadcnNoneNo official Steps component.

Accessibility

  • The list uses tablist, each trigger uses tab, and each panel uses tabpanel.
  • In non-linear mode, users can select an item trigger directly. In linear mode, movement uses the previous and next triggers.
  • Validation can block forward movement. A skippable step can bypass its validation check.
  • Give CompletedContent an accessible label because it has no matching item trigger.
  • Use at least one step. Keep controlled values in the range from zero through count.
  • Focus remains visible. State transitions stop when reduced motion is requested.

Kappa preserves Ark UI behavior.

Official Ark UI Steps documentation

API Reference

Steps.Root

PropTypeDefaultDescription
countnumber—Total number of indexed steps.
stepnumber—Controlled zero-based step. Completion is count.
defaultStepnumber0Initial uncontrolled step.
orientation"horizontal" | "vertical""horizontal"List direction.
linearbooleanfalseRequires progress through the navigation API in order.
isStepValid(index: number) => boolean—Checks a step before forward movement.
isStepSkippable(index: number) => boolean—Allows forward movement without validation for a step.
dir"ltr" | "rtl"inheritedOverrides the inherited direction.

Steps.List

PropTypeDefaultDescription
size"sm" | "base""base"Marker and label density.
asChildbooleanfalseMerges list behavior into its child.

Steps.Item and Steps.Content

PropTypeDefaultDescription
indexnumber—Required zero-based step index.
asChildbooleanfalseMerges part behavior into its child.

Parts

PartElementDescription
Steps.RootdivOwns the step state.
Steps.ListdivContains the indexed items.
Steps.ItemdivProvides one index to its parts.
Steps.TriggerbuttonSelects an item in non-linear mode.
Steps.IndicatordivShows current, complete, or incomplete state.
Steps.SeparatordivConnects adjacent items.
Steps.ContentdivPanel for one indexed item.
Steps.CompletedContentdivPanel shown when step equals count.
Steps.PrevTriggerbuttonMoves to the previous step.
Steps.NextTriggerbuttonMoves to the next step.
Steps.ProgressdivReports and shows completion percentage.

Events

EventPayloadDescription
stepChangeStepChangeDetailsRuns when the active step changes.
stepCompletevoidRuns when the value reaches count.
stepInvalidStepsInvalidDetailsRuns when validation blocks forward movement.
update:stepnumberSupports v-model:step.

Exports

ExportDescription
StepsRoot component with all compound parts.
StepsRoot … StepsItemContextNamed component exports.
useStepsCreates a controlled Ark UI steps machine.
useStepsContextReads the root machine.
useStepsItemContextReads state for the current item.
STEPS_SIZESSupported list sizes.