"use client";
import { useState } from "react";
import {
Sparkles,
Zap,
Users,
Shield,
ChevronLeft,
ChevronRight,
Rocket,
Layout,
Bell,
BarChart3,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { Progress } from "@/components/ui/progress";
import { cn } from "@/lib/utils";
type OnboardingStep = {
id: string;
title: string;
description: string;
icon: React.ElementType;
features?: { icon: React.ElementType; title: string; description: string }[];
};
const onboardingSteps: OnboardingStep[] = [
{
id: "welcome",
title: "Welcome to the Platform",
description:
"We're excited to have you here! Let's take a quick tour of the key features that will help you get the most out of your experience.",
icon: Sparkles,
},
{
id: "dashboard",
title: "Your Personal Dashboard",
description:
"Everything you need in one place. Your dashboard gives you a complete overview of your activity and quick access to all features.",
icon: Layout,
features: [
{
icon: BarChart3,
title: "Analytics",
description: "Track your progress with detailed insights",
},
{
icon: Bell,
title: "Notifications",
description: "Stay updated with real-time alerts",
},
],
},
{
id: "collaboration",
title: "Team Collaboration",
description:
"Work together seamlessly with your team. Invite members, assign roles, and collaborate in real-time.",
icon: Users,
features: [
{
icon: Users,
title: "Team Spaces",
description: "Create dedicated workspaces for each team",
},
{
icon: Shield,
title: "Permissions",
description: "Control access with granular permissions",
},
],
},
{
id: "ready",
title: "You're All Set!",
description:
"You're ready to start exploring. If you ever need help, our support team is just a click away.",
icon: Rocket,
},
];
export const title = "React Dialog Block Onboarding Welcome";
export default function DialogOnboardingWelcome() {
const [open, setOpen] = useState(false);
const [currentStep, setCurrentStep] = useState(0);
const step = onboardingSteps[currentStep];
const Icon = step.icon;
const progress = ((currentStep + 1) / onboardingSteps.length) * 100;
const isFirstStep = currentStep === 0;
const isLastStep = currentStep === onboardingSteps.length - 1;
const handleNext = () => {
if (isLastStep) {
handleComplete();
} else {
setCurrentStep((prev) => prev + 1);
}
};
const handlePrevious = () => {
setCurrentStep((prev) => Math.max(0, prev - 1));
};
const handleSkip = () => {
setOpen(false);
setCurrentStep(0);
};
const handleComplete = () => {
// In real app: mark onboarding as completed, redirect to dashboard
setOpen(false);
setCurrentStep(0);
};
const handleOpenChange = (newOpen: boolean) => {
setOpen(newOpen);
if (!newOpen) {
setTimeout(() => setCurrentStep(0), 200);
}
};
return (
<Dialog open={open} onOpenChange={handleOpenChange}>
<div className="flex min-h-[350px] items-center justify-center">
<DialogTrigger asChild>
<Button variant="outline">
<Sparkles className="mr-2 h-4 w-4" />
Start Tour
</Button>
</DialogTrigger>
</div>
<DialogContent className="sm:max-w-md">
<DialogHeader className="text-center">
<div className="flex justify-center mb-4">
<div className="flex h-12 w-12 items-center justify-center rounded-full border-2 border-primary">
<Icon className="h-6 w-6 text-primary" />
</div>
</div>
<DialogTitle>{step.title}</DialogTitle>
<DialogDescription className="text-center">
{step.description}
</DialogDescription>
</DialogHeader>
<div className="py-4">
{/* Feature Highlights */}
{step.features && (
<div className="space-y-3 mb-6">
{step.features.map((feature) => {
const FeatureIcon = feature.icon;
return (
<div
key={feature.title}
className="flex items-start gap-3 rounded-lg border p-3"
>
<div className="flex h-8 w-8 items-center justify-center rounded-md border shrink-0">
<FeatureIcon className="h-4 w-4" />
</div>
<div>
<p className="text-sm font-medium">{feature.title}</p>
<p className="text-xs text-muted-foreground">
{feature.description}
</p>
</div>
</div>
);
})}
</div>
)}
{/* Progress Section */}
<div className="space-y-3">
<Progress value={progress} className="h-1" />
<div className="flex items-center justify-center gap-1.5">
{onboardingSteps.map((_, index) => (
<button
key={index}
onClick={() => setCurrentStep(index)}
className={cn(
"h-2 w-2 rounded-full transition-colors",
index === currentStep
? "bg-primary"
: index < currentStep
? "bg-primary/50"
: "bg-muted"
)}
aria-label={`Go to step ${index + 1}`}
/>
))}
</div>
<p className="text-center text-xs text-muted-foreground">
Step {currentStep + 1} of {onboardingSteps.length}
</p>
</div>
</div>
{/* Navigation */}
<div className="flex items-center justify-between pt-2 border-t">
<Button variant="ghost" size="sm" onClick={handleSkip}>
Skip tour
</Button>
<div className="flex gap-2">
{!isFirstStep && (
<Button variant="outline" size="sm" onClick={handlePrevious}>
<ChevronLeft className="mr-1 h-4 w-4" />
Back
</Button>
)}
<Button size="sm" onClick={handleNext}>
{isLastStep ? (
<>
<Rocket className="mr-2 h-4 w-4" />
Get Started
</>
) : (
<>
Next
<ChevronRight className="ml-1 h-4 w-4" />
</>
)}
</Button>
</div>
</div>
</DialogContent>
</Dialog>
);
}