import React, { useState } from "react"; import { motion, AnimatePresence } from "framer-motion"; import { Check, ChevronRight, ChevronLeft, User, Building, CreditCard, CheckCircle2, AlertCircle, Sparkles, } from "lucide-react"; export interface Step { id: number; title: string; description: string; icon: React.ReactNode; } const steps: Step[] = [ { id: 1, title: "Account Info", description: "Personal credentials", icon: , }, { id: 2, title: "Organization", description: "Company details", icon: , }, { id: 3, title: "Billing Plan", description: "Select subscription", icon: , }, { id: 4, title: "Review & Submit", description: "Final verification", icon: , }, ]; const springPhysics = { type: "spring", stiffness: 380, damping: 26, }; export default function FormWizardPattern() { const [currentStep, setCurrentStep] = useState(1); const [direction, setDirection] = useState(1); const [isSubmitted, setIsSubmitted] = useState(false); // Form State const [fullName, setFullName] = useState(""); const [email, setEmail] = useState(""); const [companyName, setCompanyName] = useState(""); const [teamSize, setTeamSize] = useState("1-10"); const [selectedPlan, setSelectedPlan] = useState<"starter" | "pro" | "enterprise">("pro"); // Error State const [errors, setErrors] = useState>({}); const validateStep = (step: number): boolean => { const newErrors: Record = {}; if (step === 1) { if (!fullName.trim()) newErrors.fullName = "Full name is required"; if (!email.trim()) { newErrors.email = "Email address is required"; } else if (!/\S+@\S+\.\S+/.test(email)) { newErrors.email = "Enter a valid email address"; } } else if (step === 2) { if (!companyName.trim()) newErrors.companyName = "Company name is required"; } setErrors(newErrors); return Object.keys(newErrors).length === 0; }; const handleNext = () => { if (validateStep(currentStep)) { setDirection(1); setCurrentStep((prev) => Math.min(prev + 1, steps.length)); } }; const handleBack = () => { setDirection(-1); setErrors({}); setCurrentStep((prev) => Math.max(prev - 1, 1)); }; const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (validateStep(currentStep)) { setIsSubmitted(true); } }; const handleReset = () => { setIsSubmitted(false); setCurrentStep(1); setFullName(""); setEmail(""); setCompanyName(""); setSelectedPlan("pro"); setErrors({}); }; return (
{/* Header */}

Multi-Step Form Wizard

Guided setup wizard with per-step validation, spring slide transitions, and accessibility.

{/* Step Indicator Header */} {!isSubmitted && ( )} {/* Form Content */} {isSubmitted ? ( /* Final Success State */

Account Created Successfully!

Welcome aboard, {fullName}. A confirmation email has been sent to{" "} {email}.

) : (
{/* Step 1: Personal Info */} {currentStep === 1 && (

Step 1: Personal Account Info

setFullName(e.target.value)} placeholder="Jane Doe" aria-invalid={!!errors.fullName} aria-describedby={errors.fullName ? "fullname-error" : undefined} className={`w-full px-3.5 py-2.5 rounded-xl border text-sm bg-white dark:bg-slate-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 ${ errors.fullName ? "border-red-500 text-red-900 focus-visible:ring-red-500" : "border-slate-300 dark:border-slate-700" }`} /> {errors.fullName && (

{errors.fullName}

)}
setEmail(e.target.value)} placeholder="jane@company.com" aria-invalid={!!errors.email} aria-describedby={errors.email ? "email-error" : undefined} className={`w-full px-3.5 py-2.5 rounded-xl border text-sm bg-white dark:bg-slate-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 ${ errors.email ? "border-red-500 text-red-900 focus-visible:ring-red-500" : "border-slate-300 dark:border-slate-700" }`} /> {errors.email && (

{errors.email}

)}
)} {/* Step 2: Organization Info */} {currentStep === 2 && (

Step 2: Organization Details

setCompanyName(e.target.value)} placeholder="Acme Inc." aria-invalid={!!errors.companyName} aria-describedby={errors.companyName ? "company-error" : undefined} className={`w-full px-3.5 py-2.5 rounded-xl border text-sm bg-white dark:bg-slate-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 ${ errors.companyName ? "border-red-500 focus-visible:ring-red-500" : "border-slate-300 dark:border-slate-700" }`} /> {errors.companyName && (

{errors.companyName}

)}
)} {/* Step 3: Billing Plan */} {currentStep === 3 && (

Step 3: Select Plan

{[ { id: "starter", name: "Starter", price: "$19/mo" }, { id: "pro", name: "Pro", price: "$49/mo" }, { id: "enterprise", name: "Enterprise", price: "Custom" }, ].map((plan) => ( ))}
)} {/* Step 4: Review Summary */} {currentStep === 4 && (

Step 4: Review & Confirm

Name {fullName}
Email {email}
Company {companyName} ({teamSize})
Plan {selectedPlan} Plan
)}
{/* Navigation Controls */}
{currentStep > 1 ? ( Back ) : (
)} {currentStep < steps.length ? ( Next ) : ( Confirm & Submit )}
)}
); }