FluxUI Pro is live - modern UI, powerful animations, zero hassle.
Components
Stepper

Stepper

Interactive stepper component with progress tracking and customizable step content.

Step 1

First step

Step 2

Second step

Step 3

Third step

Step 1 content

Installation

1

Install the packages

npm i motion clsx tailwind-merge
2

Add util file

lib/util.ts
import { ClassValue, clsx } from "clsx"; import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); }
3

Copy and paste the following code into your project

stepper.tsx
"use client"; import { cn } from "@/lib/utils"; import { motion } from "motion/react"; import React, { useState } from "react"; import { FiCheck, FiChevronRight } from "react-icons/fi"; interface Step { id: string; title: string; description?: string; content?: React.ReactNode; } interface StepperProps { steps?: Step[]; currentStep?: number; onStepChange?: (step: number) => void; orientation?: "horizontal" | "vertical"; showContent?: boolean; } const Stepper: React.FC<StepperProps> = ({ steps = [ { id: "1", title: "Step 1", description: "First step", content: <div>Step 1 content</div> }, { id: "2", title: "Step 2", description: "Second step", content: <div>Step 2 content</div> }, { id: "3", title: "Step 3", description: "Third step", content: <div>Step 3 content</div> }, ], currentStep = 0, onStepChange = () => {}, orientation = "horizontal", showContent = true }) => { const [activeStep, setActiveStep] = useState(currentStep); const handleStepClick = (index: number) => { setActiveStep(index); onStepChange(index); }; const isCompleted = (index: number) => index < activeStep; const isActive = (index: number) => index === activeStep; return ( <div className="w-full max-w-2xl p-6"> <div className={cn( "flex", orientation === "vertical" && "flex-col space-y-8", orientation === "horizontal" && "justify-between" )}> {steps.map((step, index) => ( <React.Fragment key={step.id}> <motion.div className={cn( "flex items-center", orientation === "vertical" && "space-x-4", orientation === "horizontal" && "flex-col items-center space-y-2 flex-1" )} initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: index * 0.1 }} > {/* Step Circle */} <motion.button onClick={() => handleStepClick(index)} className={cn( "relative flex items-center justify-center w-10 h-10 rounded-full border-2 transition-all", isCompleted(index) ? "bg-green-500 border-green-500 text-white" : isActive(index) ? "border-cyan-500 text-cyan-500" : "border-neutral-600 text-neutral-400 hover:border-neutral-400" )} whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.95 }} > {isCompleted(index) ? ( <FiCheck className="h-5 w-5" /> ) : ( <span className="text-sm font-medium">{index + 1}</span> )} </motion.button> {/* Step Content */} <div className={cn( orientation === "vertical" && "flex-1", orientation === "horizontal" && "text-center" )}> <h3 className={cn( "font-medium", isActive(index) ? "text-white" : "text-neutral-300" )}> {step.title} </h3> {step.description && ( <p className="text-sm text-neutral-400 mt-1"> {step.description} </p> )} </div> </motion.div> {/* Connector Line */} {index < steps.length - 1 && ( <motion.div className={cn( "flex items-center", orientation === "horizontal" && "flex-1 mx-4", orientation === "vertical" && "ml-6 mb-8" )} initial={{ scaleX: 0 }} animate={{ scaleX: 1 }} transition={{ delay: index * 0.1 + 0.2 }} > <div className={cn( "bg-neutral-600", orientation === "horizontal" && "h-0.5 w-full", orientation === "vertical" && "w-0.5 h-8" )} /> <FiChevronRight className={cn( "text-neutral-600", orientation === "horizontal" && "hidden", orientation === "vertical" && "ml-2" )} /> </motion.div> )} </React.Fragment> ))} </div> {/* Step Content */} {showContent && steps[activeStep] && ( <motion.div className="mt-8 p-4 bg-neutral-800 rounded-lg" key={activeStep} initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.3 }} > {steps[activeStep].content} </motion.div> )} </div> ); }; export default Stepper;
4

Update the import paths to match your project setup

Props

PropTypeDefaultDescription
stepsStep[][]Array of step objects with id, title, description, and content.
currentStepnumber0Current active step index.
onStepChangefunction() => {}Callback when step changes.
orientationstringhorizontalStepper orientation (horizontal or vertical).
showContentbooleantrueShow step content below the stepper.