Skip to content

Commit f02d104

Browse files
committed
Add onboarding flow component
Introduces an OnboardingFlow React component to guide new users through platform features. Includes step navigation, progress bar, illustrations, and completion/skip handlers.
1 parent b5e2021 commit f02d104

1 file changed

Lines changed: 191 additions & 0 deletions

File tree

components/onboarding-flow.tsx

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
"use client"
2+
3+
import { useState, useEffect } from "react"
4+
import { X, Check, ArrowRight, ArrowLeft, Sparkles } from "lucide-react"
5+
import { Button } from "./ui/button"
6+
7+
export interface OnboardingProps {
8+
onComplete: () => void
9+
onSkip: () => void
10+
}
11+
12+
const steps = [
13+
{
14+
title: "Welcome to lab68dev Platform!",
15+
description: "Let's take a quick tour to help you get started with our developer platform.",
16+
illustration: (
17+
<div className="w-full h-48 flex items-center justify-center bg-gradient-to-br from-primary/20 to-purple-500/20 border border-primary/20">
18+
<Sparkles className="h-24 w-24 text-primary" />
19+
</div>
20+
),
21+
},
22+
{
23+
title: "Create Your First Project",
24+
description: "Projects help you organize your work. Head to the Projects section to create one.",
25+
illustration: (
26+
<svg className="w-full h-48" viewBox="0 0 200 200" fill="none">
27+
<rect x="40" y="60" width="120" height="80" stroke="currentColor" strokeWidth="2" className="text-primary" fill="none" />
28+
<rect x="55" y="75" width="35" height="25" fill="currentColor" className="text-primary/30" />
29+
<rect x="100" y="75" width="45" height="25" fill="currentColor" className="text-primary/30" />
30+
<rect x="55" y="110" width="90" height="3" fill="currentColor" className="text-muted-foreground/30" />
31+
</svg>
32+
),
33+
},
34+
{
35+
title: "Collaborate with Your Team",
36+
description: "Use Chat, Whiteboard, and Meetings to collaborate in real-time with your team members.",
37+
illustration: (
38+
<svg className="w-full h-48" viewBox="0 0 200 200" fill="none">
39+
<circle cx="70" cy="80" r="15" fill="currentColor" className="text-blue-500/30" />
40+
<circle cx="100" cy="80" r="15" fill="currentColor" className="text-green-500/30" />
41+
<circle cx="130" cy="80" r="15" fill="currentColor" className="text-purple-500/30" />
42+
<rect x="50" y="110" width="100" height="40" rx="5" stroke="currentColor" strokeWidth="2" className="text-primary" fill="none" />
43+
</svg>
44+
),
45+
},
46+
{
47+
title: "Stay Organized with Todo & Planning",
48+
description: "Keep track of your tasks and plan your sprints with our built-in productivity tools.",
49+
illustration: (
50+
<svg className="w-full h-48" viewBox="0 0 200 200" fill="none">
51+
<rect x="60" y="50" width="80" height="12" rx="2" stroke="currentColor" strokeWidth="2" className="text-muted-foreground" fill="none" />
52+
<rect x="60" y="70" width="80" height="12" rx="2" stroke="currentColor" strokeWidth="2" className="text-muted-foreground" fill="none" />
53+
<rect x="60" y="90" width="80" height="12" rx="2" fill="currentColor" className="text-green-500/30" stroke="currentColor" strokeWidth="2" />
54+
<path d="M70 96 L75 101 L85 91" stroke="white" strokeWidth="2" fill="none" />
55+
</svg>
56+
),
57+
},
58+
{
59+
title: "You're All Set!",
60+
description: "Start building amazing things with lab68dev. Use Cmd/Ctrl + K anytime to quickly navigate.",
61+
illustration: (
62+
<div className="w-full h-48 flex items-center justify-center bg-gradient-to-br from-green-500/20 to-blue-500/20 border border-green-500/20">
63+
<Check className="h-24 w-24 text-green-500" />
64+
</div>
65+
),
66+
},
67+
]
68+
69+
export function OnboardingFlow({ onComplete, onSkip }: OnboardingProps) {
70+
const [currentStep, setCurrentStep] = useState(0)
71+
const [isVisible, setIsVisible] = useState(false)
72+
73+
useEffect(() => {
74+
// Fade in animation
75+
setTimeout(() => setIsVisible(true), 100)
76+
}, [])
77+
78+
const handleNext = () => {
79+
if (currentStep < steps.length - 1) {
80+
setCurrentStep(currentStep + 1)
81+
} else {
82+
handleComplete()
83+
}
84+
}
85+
86+
const handlePrevious = () => {
87+
if (currentStep > 0) {
88+
setCurrentStep(currentStep - 1)
89+
}
90+
}
91+
92+
const handleComplete = () => {
93+
setIsVisible(false)
94+
setTimeout(() => onComplete(), 300)
95+
}
96+
97+
const handleSkipOnboarding = () => {
98+
setIsVisible(false)
99+
setTimeout(() => onSkip(), 300)
100+
}
101+
102+
return (
103+
<div
104+
className={`fixed inset-0 z-50 flex items-center justify-center px-4 transition-opacity duration-300 ${
105+
isVisible ? "opacity-100" : "opacity-0"
106+
}`}
107+
>
108+
{/* Backdrop */}
109+
<div className="absolute inset-0 bg-background/95 backdrop-blur-sm" />
110+
111+
{/* Modal */}
112+
<div className="relative w-full max-w-2xl border-2 border-primary bg-background shadow-2xl transform transition-transform duration-300">
113+
{/* Close Button */}
114+
<button
115+
onClick={handleSkipOnboarding}
116+
className="absolute top-4 right-4 p-2 hover:bg-muted transition-colors z-10"
117+
aria-label="Close onboarding"
118+
>
119+
<X className="h-5 w-5" />
120+
</button>
121+
122+
{/* Content */}
123+
<div className="p-8 sm:p-12">
124+
{/* Progress Bar */}
125+
<div className="mb-8">
126+
<div className="flex gap-2">
127+
{steps.map((_, index) => (
128+
<div
129+
key={index}
130+
className={`h-1 flex-1 transition-colors ${
131+
index <= currentStep ? "bg-primary" : "bg-border"
132+
}`}
133+
/>
134+
))}
135+
</div>
136+
<div className="mt-2 text-xs text-muted-foreground text-right">
137+
Step {currentStep + 1} of {steps.length}
138+
</div>
139+
</div>
140+
141+
{/* Illustration */}
142+
<div className="mb-8">{steps[currentStep].illustration}</div>
143+
144+
{/* Text Content */}
145+
<div className="text-center space-y-4 mb-8">
146+
<h2 className="text-2xl sm:text-3xl font-bold">
147+
{steps[currentStep].title}
148+
</h2>
149+
<p className="text-muted-foreground text-sm sm:text-base max-w-md mx-auto">
150+
{steps[currentStep].description}
151+
</p>
152+
</div>
153+
154+
{/* Navigation Buttons */}
155+
<div className="flex items-center justify-between gap-4">
156+
<Button
157+
onClick={handlePrevious}
158+
variant="outline"
159+
disabled={currentStep === 0}
160+
className="gap-2"
161+
>
162+
<ArrowLeft className="h-4 w-4" />
163+
Previous
164+
</Button>
165+
166+
<button
167+
onClick={handleSkipOnboarding}
168+
className="text-sm text-muted-foreground hover:text-foreground transition-colors"
169+
>
170+
Skip tour
171+
</button>
172+
173+
<Button onClick={handleNext} className="gap-2">
174+
{currentStep === steps.length - 1 ? (
175+
<>
176+
Get Started
177+
<Check className="h-4 w-4" />
178+
</>
179+
) : (
180+
<>
181+
Next
182+
<ArrowRight className="h-4 w-4" />
183+
</>
184+
)}
185+
</Button>
186+
</div>
187+
</div>
188+
</div>
189+
</div>
190+
)
191+
}

0 commit comments

Comments
 (0)