MultiStepForm
multistepform-1779378816985.tsx
'use client'
import { useState } from 'react'
const STEPS = [
{ title: 'Account', fields: ['name', 'email'] },
{ title: 'Profile', fields: ['role', 'company'] },
{ title: 'Confirm', fields: [] },
]
export default function MultiStepForm() {
const [step, setStep] = useState(0)
const [data, setData] = useState({ name: '', email: '', role: '', company: '' })
const [done, setDone] = useState(false)
const set = (k: string) => (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) =>
setData(d => ({ ...d, [k]: e.target.value }))
const canNext = step === 0 ? data.name && data.email : step === 1 ? data.role : true
if (done) return (
<div style={{ padding: 40, background: '#0A0A0A', display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: 400 }}>
<div style={{ textAlign: 'center' }}>
<div style={{ fontSize: 56, marginBottom: 16 }}>🎉</div>
<div style={{ color: '#F5F5F0', fontSize: 22, fontWeight: 700, marginBottom: 8 }}>Account Created!</div>
<div style={{ color: 'rgba(255,255,255,0.5)', fontSize: 14 }}>Welcome, {data.name}</div>
<button onClick={() => { setDone(false); setStep(0); setData({ name:'',email:'',role:'',company:'' }) }}
style={{ marginTop: 24, background: '#C9A84C', color: '#0A0A0A', border: 'none', borderRadius: 8, padding: '10px 24px', fontWeight: 700, cursor: 'pointer', fontSize: 14 }}>
Start over
</button>
</div>
</div>
)
return (
<div style={{ padding: 40, background: '#0A0A0A', display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: 400 }}>
<div style={{ width: 380 }}>
{/* Progress */}
<div style={{ display: 'flex', gap: 8, marginBottom: 32, alignItems: 'center' }}>
{STEPS.map((s, i) => (
<div key={i} style={{ display: 'flex', alignItems: 'center', flex: i < STEPS.length - 1 ? 1 : 'none' }}>
<div style={{
width: 28, height: 28, borderRadius: '50%', flexShrink: 0,
background: i < step ? '#22c55e' : i === step ? '#C9A84C' : 'rgba(255,255,255,0.1)',
color: i <= step ? '#0A0A0A' : 'rgba(255,255,255,0.4)',
display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 12, fontWeight: 700,
transition: 'all 0.3s',
}}>{i < step ? '✓' : i + 1}</div>
{i < STEPS.length - 1 && (
<div style={{ flex: 1, height: 2, margin: '0 8px', background: i < step ? '#22c55e' : 'rgba(255,255,255,0.08)', transition: 'background 0.3s' }} />
)}
</div>
))}
</div>
<div style={{ color: '#F5F5F0', fontSize: 20, fontWeight: 700, marginBottom: 8 }}>{STEPS[step].title}</div>
<div style={{ color: 'rgba(255,255,255,0.4)', fontSize: 13, marginBottom: 24 }}>Step {step + 1} of {STEPS.length}</div>
{/* Fields */}
<div style={{ display: 'flex', flexDirection: 'column', gap: 16, marginBottom: 32 }}>
{step === 0 && <>
<input placeholder="Full name *" value={data.name} onChange={set('name')} style={inp} />
<input placeholder="Email address *" value={data.email} onChange={set('email')} style={inp} />
</>}
{step === 1 && <>
<select value={data.role} onChange={set('role')} style={inp}>
<option value="">Select your role *</option>
{['Developer', 'Designer', 'Product Manager', 'Founder', 'Other'].map(r => <option key={r}>{r}</option>)}
</select>
<input placeholder="Company (optional)" value={data.company} onChange={set('company')} style={inp} />
</>}
{step === 2 && (
<div style={{ background: 'rgba(255,255,255,0.03)', border: '1px solid rgba(255,255,255,0.08)', borderRadius: 10, padding: 20 }}>
{[['Name', data.name], ['Email', data.email], ['Role', data.role], ['Company', data.company || '—']].map(([k,v]) => (
<div key={k} style={{ display: 'flex', justifyContent: 'space-between', padding: '8px 0', borderBottom: '1px solid rgba(255,255,255,0.04)' }}>
<span style={{ color: 'rgba(255,255,255,0.4)', fontSize: 13 }}>{k}</span>
<span style={{ color: '#F5F5F0', fontSize: 13, fontWeight: 500 }}>{v}</span>
</div>
))}
</div>
)}
</div>
<div style={{ display: 'flex', gap: 12 }}>
{step > 0 && <button onClick={() => setStep(s => s - 1)} style={{ flex: 1, background: 'rgba(255,255,255,0.06)', color: '#F5F5F0', border: '1px solid rgba(255,255,255,0.1)', borderRadius: 8, padding: '12px', cursor: 'pointer', fontSize: 14, fontWeight: 600 }}>Back</button>}
<button onClick={() => step < STEPS.length - 1 ? setStep(s => s + 1) : setDone(true)} disabled={!canNext}
style={{ flex: 1, background: canNext ? '#C9A84C' : 'rgba(255,255,255,0.08)', color: canNext ? '#0A0A0A' : 'rgba(255,255,255,0.3)', border: 'none', borderRadius: 8, padding: '12px', cursor: canNext ? 'pointer' : 'default', fontSize: 14, fontWeight: 700 }}>
{step === STEPS.length - 1 ? 'Create account' : 'Continue'}
</button>
</div>
</div>
</div>
)
}
const inp: React.CSSProperties = {
background: 'rgba(255,255,255,0.04)', border: '1.5px solid rgba(255,255,255,0.1)',
borderRadius: 10, color: '#F5F5F0', fontSize: 14, padding: '12px 16px', outline: 'none', width: '100%', boxSizing: 'border-box'
}Component info
CategoryForms
Frameworkreact
TierFREE
Views0
Copies0
About
Multi-step wizard form with progress bar, validation per step, and animated transitions