OnboardingChecklist
onboardingchecklist-1779379195580.tsx
'use client'
import { useState } from 'react'
const STEPS = [
{ id: 'profile', title: 'Complete your profile', desc: 'Add your name and avatar to personalize your experience.', xp: 50 },
{ id: 'browse', title: 'Browse components', desc: 'Explore 100+ production-ready React components.', xp: 25 },
{ id: 'copy', title: 'Copy your first component', desc: 'Click the copy button on any component page.', xp: 50 },
{ id: 'mcp', title: 'Setup MCP in Claude Code', desc: 'Add Empire UI to your Claude configuration.', xp: 100 },
{ id: 'api', title: 'Get your API key', desc: 'Visit your account page to get your personal API key.', xp: 75 },
]
export default function OnboardingChecklist() {
const [done, setDone] = useState<Set<string>>(new Set(['browse']))
const total = STEPS.length
const completed = done.size
const pct = (completed / total) * 100
const xpTotal = STEPS.filter(s => done.has(s.id)).reduce((a, s) => a + s.xp, 0)
const r = 32, circ = 2 * Math.PI * r
return (
<div style={{ background: '#0A0A0A', padding: 32, maxWidth: 440, margin: '0 auto' }}>
{/* Header with ring */}
<div style={{ display: 'flex', alignItems: 'center', gap: 20, marginBottom: 28, background: '#111', border: '1px solid rgba(255,255,255,0.06)', borderRadius: 16, padding: 20 }}>
<svg width={80} height={80} viewBox="0 0 80 80" style={{ flexShrink: 0 }}>
<circle cx={40} cy={40} r={r} fill="none" stroke="rgba(255,255,255,0.06)" strokeWidth={6} />
<circle cx={40} cy={40} r={r} fill="none" stroke={completed === total ? '#22c55e' : '#C9A84C'} strokeWidth={6}
strokeDasharray={circ} strokeDashoffset={circ * (1 - pct / 100)}
strokeLinecap="round" transform="rotate(-90 40 40)" style={{ transition: 'stroke-dashoffset 0.5s ease' }} />
<text x={40} y={44} textAnchor="middle" fontSize={16} fontWeight={800} fill="#F5F5F0">{completed}/{total}</text>
</svg>
<div>
<div style={{ color: '#F5F5F0', fontSize: 18, fontWeight: 700, marginBottom: 4 }}>
{completed === total ? 'š Complete!' : 'Getting started'}
</div>
<div style={{ color: 'rgba(255,255,255,0.4)', fontSize: 13, marginBottom: 8 }}>{Math.round(pct)}% done</div>
<div style={{ background: 'rgba(201,168,76,0.12)', border: '1px solid rgba(201,168,76,0.2)', color: '#C9A84C', padding: '3px 10px', borderRadius: 20, fontSize: 12, fontWeight: 600, display: 'inline-block' }}>
ā” {xpTotal} XP earned
</div>
</div>
</div>
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
{STEPS.map(step => {
const isDone = done.has(step.id)
return (
<div key={step.id} onClick={() => setDone(s => { const n = new Set(s); isDone ? n.delete(step.id) : n.add(step.id); return n })}
style={{ display: 'flex', gap: 14, padding: '14px 16px', border: '1px solid', borderColor: isDone ? 'rgba(34,197,94,0.2)' : 'rgba(255,255,255,0.06)', borderRadius: 12, cursor: 'pointer', background: isDone ? 'rgba(34,197,94,0.04)' : 'rgba(255,255,255,0.02)', transition: 'all 0.2s' }}>
<div style={{ width: 22, height: 22, borderRadius: '50%', border: `2px solid ${isDone ? '#22c55e' : 'rgba(255,255,255,0.2)'}`, background: isDone ? '#22c55e' : 'transparent', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, marginTop: 1, transition: 'all 0.2s' }}>
{isDone && <span style={{ color: '#fff', fontSize: 12, fontWeight: 800 }}>ā</span>}
</div>
<div style={{ flex: 1 }}>
<div style={{ color: isDone ? 'rgba(255,255,255,0.4)' : '#F5F5F0', fontSize: 14, fontWeight: 600, textDecoration: isDone ? 'line-through' : 'none', marginBottom: 2, transition: 'all 0.2s' }}>{step.title}</div>
{!isDone && <div style={{ color: 'rgba(255,255,255,0.4)', fontSize: 12 }}>{step.desc}</div>}
</div>
<div style={{ color: '#C9A84C', fontSize: 11, fontWeight: 700, flexShrink: 0 }}>+{step.xp} XP</div>
</div>
)
})}
</div>
</div>
)
}Component info
CategoryOnboarding
Frameworkreact
TierFREE
Views0
Copies0
About
Onboarding checklist with progress ring, animated checkmarks, step descriptions, and completion reward