Stepper
Overview
The Stepper component helps visualize progress through a multi-step process. It's perfect for forms, wizards, or any sequential workflow in your application. The component includes support for completed states, active states, and optional descriptions for each step.
Preview
- Preview
- Code
✓
Details
Personal info
2
Address
Shipping info
3
Payment
Card details
4
Review
Final check
import { Stepper } from './components/ui';
function StepperDemo() {
return (
<Stepper
steps={[
{ label: 'Details', description: 'Personal info' },
{ label: 'Address', description: 'Shipping info' },
{ label: 'Payment', description: 'Card details' },
{ label: 'Review', description: 'Final check' },
]}
activeStep={1}
/>
);
}
Installation
- npm
- yarn
- pnpm
- manual
npx @mindfiredigital/ignix-ui add stepper
yarn @mindfiredigital/ignix-ui add stepper
pnpm @mindfiredigital/ignix-ui add stepper
import { cn } from "../../../utils/cn";
interface Step {
label: string;
description?: string;
}
interface StepperProps {
steps: Step[];
activeStep: number; // 0-based index
className?: string;
}
export const Stepper = ({ steps, activeStep, className }: StepperProps) => {
return (
<div className={cn("flex items-center justify-between w-full", className)}>
{steps.map((step, index) => {
const isActive = index === activeStep;
const isCompleted = index < activeStep;
return (
<div
key={index}
className="flex-1 flex flex-col items-center relative"
>
{/* Line connector */}
{index !== steps.length - 1 && (
<div className="absolute top-4 left-1/2 w-full h-0.5 bg-zinc-300 dark:bg-zinc-700 z-0 transform translate-x-1/2" />
)}
{/* Step circle */}
<div
className={cn(
"z-10 w-8 h-8 flex items-center justify-center rounded-full border-2 text-sm font-medium",
isCompleted
? "bg-green-500 border-green-500 text-white"
: isActive
? "bg-white dark:bg-zinc-900 border-primary text-primary"
: "bg-white dark:bg-zinc-900 border-zinc-300 text-zinc-400"
)}
>
{isCompleted ? "✓" : index + 1}
</div>
{/* Step label */}
<div className="text-center mt-2">
<div
className={cn(
"text-xs font-medium",
isActive || isCompleted
? "text-zinc-900 dark:text-white"
: "text-zinc-400"
)}
>
{step.label}
</div>
{step.description && (
<div className="text-[11px] text-zinc-500 dark:text-zinc-400">
{step.description}
</div>
)}
</div>
</div>
);
})}
</div>
);
};
Usage
Import the component:
import { Stepper } from './components/ui';
Basic Usage
function BasicStepper() {
const [currentStep, setCurrentStep] = useState(0);
const steps = [
{ label: 'Step 1' },
{ label: 'Step 2' },
{ label: 'Step 3' },
];
return (
<Stepper
steps={steps}
activeStep={currentStep}
/>
);
}
Examples
Basic Stepper
- Preview
- Code
✓
Step 1
2
Step 2
3
Step 3
<Stepper
steps={[
{ label: 'Step 1' },
{ label: 'Step 2' },
{ label: 'Step 3' },
]}
activeStep={1}
/>
With Descriptions
- Preview
- Code
✓
Account
Create account
✓
Profile
Complete profile
3
Verify
Verification
4
Done
Final step
<Stepper
steps={[
{ label: 'Account', description: 'Create account' },
{ label: 'Profile', description: 'Complete profile' },
{ label: 'Verify', description: 'Verification' },
{ label: 'Done', description: 'Final step' },
]}
activeStep={2}
/>
Interactive Example
- Preview
- Code
1
Cart
Review items
2
Shipping
Delivery info
3
Payment
Card details
function InteractiveStepper() {
const [step, setStep] = useState(0);
return (
<div className="space-y-4">
<Stepper
steps={[
{ label: 'Cart', description: 'Review items' },
{ label: 'Shipping', description: 'Delivery info' },
{ label: 'Payment', description: 'Card details' },
]}
activeStep={step}
/>
<div className="flex justify-between mt-4">
<button
onClick={() => setStep(Math.max(0, step - 1))}
disabled={step === 0}
className="px-4 py-2 bg-blue-500 text-white rounded disabled:opacity-50"
>
Previous
</button>
<button
onClick={() => setStep(Math.min(2, step + 1))}
disabled={step === 2}
className="px-4 py-2 bg-blue-500 text-white rounded disabled:opacity-50"
>
Next
</button>
</div>
</div>
);
}
Props
Prop | Type | Default | Description |
---|---|---|---|
steps | Array<{ label: string; description?: string; }> | [] | Array of step objects with labels and optional descriptions |
activeStep | number | 0 | Current active step (0-based index) |
className | string | - | Additional CSS classes |
Customization
Custom Styling
You can customize the appearance using Tailwind CSS classes:
<Stepper
className="max-w-2xl mx-auto"
steps={[
{ label: 'Start', description: 'Begin here' },
{ label: 'Middle', description: 'Continue' },
{ label: 'End', description: 'Complete' },
]}
activeStep={1}
/>
Form Integration Example
function StepperForm() {
const [currentStep, setCurrentStep] = useState(0);
const [formData, setFormData] = useState({
personal: {},
address: {},
payment: {},
});
const steps = [
{ label: 'Personal', description: 'Basic info' },
{ label: 'Address', description: 'Shipping details' },
{ label: 'Payment', description: 'Payment method' },
];
const renderStepContent = (step: number) => {
switch (step) {
case 0:
return <PersonalInfoForm data={formData.personal} onSave={handleSave} />;
case 1:
return <AddressForm data={formData.address} onSave={handleSave} />;
case 2:
return <PaymentForm data={formData.payment} onSave={handleSave} />;
default:
return null;
}
};
return (
<div className="space-y-6">
<Stepper steps={steps} activeStep={currentStep} />
<div className="mt-8">
{renderStepContent(currentStep)}
</div>
</div>
);
}