Svelte StepIndicator
Use the step indicator component to show the progress of a process.
The Step Indicator component is a simple component to show the progress of a process. It can be used to show the progress of a multi-step form or a multi-step process.
Setup #
Import the StepIndicator component in a script tag.
- Svelte
<script lang="ts">
import { StepIndicator } from "flowbite-svelte";
</script>Default step indicator #
Use the following example of a step indicator element to show a progress of step 2 out of 5.
- Svelte
<script lang="ts">
import { StepIndicator } from "flowbite-svelte";
let currentStep = 2;
let steps = ["Step 1", "Step 2", "Step 3", "Step 4", "Step 5"];
</script>
<StepIndicator {currentStep} {steps} />Clickable navigation #
The step indicator supports clickable navigation by default. Click on any step to navigate to it. Use the onStepClick callback to handle navigation events.
- Svelte
<script lang="ts">
import { StepIndicator, Button } from "flowbite-svelte";
let currentStep = $state(1);
const steps = ["Step 1", "Step 2", "Step 3", "Step 4", "Step 5"];
function handleStepClick({ current, last }: { current: number; last: number }) {
console.log(`Navigated from step ${last} to step ${current}`);
}
function next() {
if (currentStep < steps.length) {
currentStep++;
}
}
function prev() {
if (currentStep > 1) {
currentStep--;
}
}
function reset() {
currentStep = 1;
}
</script>
<div class="space-y-6">
<StepIndicator bind:currentStep {steps} onStepClick={handleStepClick} />
<div class="flex gap-2">
<Button onclick={prev} disabled={currentStep === 1}>Previous</Button>
<Button onclick={next} disabled={currentStep === steps.length}>Next</Button>
<Button onclick={reset} color="alternative">Reset</Button>
</div>
<p class="text-sm text-gray-500 dark:text-gray-400">Click on any step indicator to navigate directly to that step.</p>
</div>Clickable multi-step form #
Here’s a complete example of using the step indicator with a multi-step form. Users can click on any completed step to go back and edit their information.
- Svelte
<script lang="ts">
import { StepIndicator, Button, Label, Input } from "flowbite-svelte";
let currentStep = $state(1);
const steps = ["Personal Info", "Contact Details", "Address", "Review", "Complete"];
// Form data
let personalInfo = $state({ firstName: "", lastName: "" });
let contactInfo = $state({ email: "", phone: "" });
let addressInfo = $state({ street: "", city: "", zip: "" });
function next() {
if (currentStep < steps.length) {
currentStep++;
}
}
function prev() {
if (currentStep > 1) {
currentStep--;
}
}
function handleSubmit(e: Event) {
e.preventDefault();
next();
}
</script>
<div class="space-y-6">
<StepIndicator bind:currentStep {steps} color="primary" glow />
<form onsubmit={handleSubmit} class="space-y-4">
{#if currentStep === 1}
<div class="space-y-4">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">Personal Information</h3>
<div>
<Label for="firstName" class="mb-2">First Name</Label>
<Input type="text" id="firstName" bind:value={personalInfo.firstName} placeholder="John" required />
</div>
<div>
<Label for="lastName" class="mb-2">Last Name</Label>
<Input type="text" id="lastName" bind:value={personalInfo.lastName} placeholder="Doe" required />
</div>
</div>
{:else if currentStep === 2}
<div class="space-y-4">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">Contact Details</h3>
<div>
<Label for="email" class="mb-2">Email</Label>
<Input type="email" id="email" bind:value={contactInfo.email} placeholder="john.doe@example.com" required />
</div>
<div>
<Label for="phone" class="mb-2">Phone</Label>
<Input type="tel" id="phone" bind:value={contactInfo.phone} placeholder="+1 (555) 123-4567" required />
</div>
</div>
{:else if currentStep === 3}
<div class="space-y-4">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">Address Information</h3>
<div>
<Label for="street" class="mb-2">Street Address</Label>
<Input type="text" id="street" bind:value={addressInfo.street} placeholder="123 Main St" required />
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<Label for="city" class="mb-2">City</Label>
<Input type="text" id="city" bind:value={addressInfo.city} placeholder="New York" required />
</div>
<div>
<Label for="zip" class="mb-2">ZIP Code</Label>
<Input type="text" id="zip" bind:value={addressInfo.zip} placeholder="10001" required />
</div>
</div>
</div>
{:else if currentStep === 4}
<div class="space-y-4">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">Review Your Information</h3>
<div class="rounded-lg border border-gray-200 p-4 dark:border-gray-700">
<dl class="space-y-2">
<div class="flex justify-between">
<dt class="font-medium text-gray-500 dark:text-gray-400">Name:</dt>
<dd class="text-gray-900 dark:text-white">{personalInfo.firstName} {personalInfo.lastName}</dd>
</div>
<div class="flex justify-between">
<dt class="font-medium text-gray-500 dark:text-gray-400">Email:</dt>
<dd class="text-gray-900 dark:text-white">{contactInfo.email}</dd>
</div>
<div class="flex justify-between">
<dt class="font-medium text-gray-500 dark:text-gray-400">Phone:</dt>
<dd class="text-gray-900 dark:text-white">{contactInfo.phone}</dd>
</div>
<div class="flex justify-between">
<dt class="font-medium text-gray-500 dark:text-gray-400">Address:</dt>
<dd class="text-gray-900 dark:text-white">{addressInfo.street}, {addressInfo.city} {addressInfo.zip}</dd>
</div>
</dl>
</div>
<p class="text-sm text-gray-500 dark:text-gray-400">Click on any step indicator above to go back and edit your information.</p>
</div>
{:else if currentStep === 5}
<div class="space-y-4 text-center">
<div class="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-green-100 dark:bg-green-900">
<svg class="h-6 w-6 text-green-600 dark:text-green-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
</div>
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">Registration Complete!</h3>
<p class="text-gray-500 dark:text-gray-400">Thank you for completing the form.</p>
</div>
{/if}
<div class="flex gap-2">
{#if currentStep > 1 && currentStep < 5}
<Button type="button" onclick={prev} color="alternative">Previous</Button>
{/if}
{#if currentStep < 4}
<Button type="submit">Next</Button>
{:else if currentStep === 4}
<Button type="submit" color="green">Complete</Button>
{/if}
</div>
</form>
</div>Non-clickable #
Set clickable={false} to disable click navigation on the step indicators.
- Svelte
<script lang="ts">
import { StepIndicator } from "flowbite-svelte";
let currentStep = $state(3);
const steps = ["Step 1", "Step 2", "Step 3", "Step 4", "Step 5"];
</script>
<div class="space-y-4">
<StepIndicator bind:currentStep {steps} clickable={false} />
<p class="text-sm text-gray-500 dark:text-gray-400">
Step indicators are non-clickable when <code class="text-xs">clickable={"{false}"}</code>
is set.
</p>
</div>Glow #
Use the glow prop to add a glow effect to the current step.
- Svelte
<script lang="ts">
import { StepIndicator } from "flowbite-svelte";
let currentStep = 2;
let steps = ["Step 1", "Step 2", "Step 3", "Step 4", "Step 5"];
</script>
<StepIndicator {currentStep} {steps} glow />Hide label #
Use the hideLabel prop to hide the label of the current step.
- Svelte
<script lang="ts">
import { StepIndicator } from "flowbite-svelte";
let currentStep = 2;
let steps = ["Step 1", "Step 2", "Step 3", "Step 4", "Step 5"];
</script>
<StepIndicator {currentStep} {steps} hideLabel />Sizes #
Use the size prop to change the size of a step indicator.
- Svelte
<script lang="ts">
import { StepIndicator, type StepIndicatorProps, Radio, Label } from "flowbite-svelte";
const sizes = ["xs", "sm", "md", "lg", "xl"];
let size: StepIndicatorProps["size"] = $state("xs");
let currentStep = 2;
let steps = ["Step 1", "Step 2", "Step 3", "Step 4", "Step 5"];
</script>
<div class="my-4">
<StepIndicator {currentStep} {steps} bind:size />
</div>
<div class="flex flex-wrap space-x-2">
<Label class="mb-4 w-full font-bold">Size</Label>
{#each sizes as sizeOption}
<Radio class="my-1" classes={{ label: "w-24" }} name="size" bind:group={size} value={sizeOption}>
{sizeOption}
</Radio>
{/each}
</div>Colors #
Use the color prop to change the color of a step indicator.
- Svelte
<script lang="ts">
import { StepIndicator, type StepIndicatorProps, Radio, Label } from "flowbite-svelte";
const colors = ["primary", "secondary", "gray", "red", "yellow", "green", "indigo", "purple", "pink", "blue"];
let color: StepIndicatorProps["color"] = $state("green");
let currentStep = 2;
let steps = ["Step 1", "Step 2", "Step 3", "Step 4", "Step 5"];
type SimpleRadioColor = "primary" | "secondary" | "gray" | "red" | "yellow" | "green" | "indigo" | "purple" | "pink" | "blue";
</script>
<div class="my-4">
<StepIndicator {currentStep} {steps} bind:color />
</div>
<div class="flex flex-wrap space-x-2">
<Label class="mb-4 w-full font-bold">Color</Label>
{#each colors as colorOption}
<Radio class="my-1" classes={{ label: "w-24" }} name="color" bind:group={color} color={colorOption as SimpleRadioColor} value={colorOption as StepIndicatorProps["color"]}>
{colorOption}
</Radio>
{/each}
</div>Component data #
The component has the following props, type, and default values. See types page for type information.
StepIndicator styling #
- Use the
classprop to overwrite the default class.