import * as React from 'react'; import { Dialog } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; import { cn } from '@/lib/utils'; import { CheckCircle, ChevronRight, ChevronLeft } from 'lucide-react'; /** * OnboardingStep - Single step in the onboarding flow */ export interface OnboardingStep { title: string; description: string; content?: React.ReactNode; } /** * OnboardingProps - Properties for the Onboarding component */ export interface OnboardingProps { /** * Whether the onboarding is open */ open: boolean; /** * Callback when onboarding is closed */ onClose: () => void; /** * Steps to display in the onboarding flow */ steps: OnboardingStep[]; /** * Optional callback when onboarding is completed */ onComplete?: () => void; } /** * Onboarding - Multi-step onboarding flow component * * Guides new users through key features of the application. * Displays steps sequentially with navigation controls. * * @example * ```tsx * setShowOnboarding(false)} * steps={[ * { title: 'Welcome', description: 'Welcome to Veza!' }, * { title: 'Library', description: 'Manage your tracks here' }, * ]} * onComplete={() => console.log('Onboarding complete')} * /> * ``` */ export function Onboarding({ open, onClose, steps, onComplete, }: OnboardingProps) { const [currentStep, setCurrentStep] = React.useState(0); const handleNext = () => { if (currentStep < steps.length - 1) { setCurrentStep(currentStep + 1); } else { handleComplete(); } }; const handlePrevious = () => { if (currentStep > 0) { setCurrentStep(currentStep - 1); } }; const handleSkip = () => { handleComplete(); }; const handleComplete = () => { onComplete?.(); onClose(); // Reset to first step for next time setCurrentStep(0); }; if (!open || steps.length === 0) { return null; } const step = steps[currentStep]; const isFirstStep = currentStep === 0; const isLastStep = currentStep === steps.length - 1; return ( {/* Progress indicator */}
{steps.map((_, index) => (
))}
{/* Navigation buttons */}
{!isFirstStep && ( )}
} >

{step.title}

{step.description}

{step.content && (
{step.content}
)}
); }