/** * LoadingSpinner - Animated loading spinner for web * * Features: * - Multiple sizes (sm, md, lg, xl) * - Optional loading message * - Full-screen mode option * - Tailwind CSS styling * * @example * ```tsx * * * * ``` */ import { cn } from '@/lib/utils'; interface LoadingSpinnerProps { size?: 'sm' | 'md' | 'lg' | 'xl'; color?: 'primary' | 'white' | 'gray'; message?: string; fullScreen?: boolean; className?: string; } // Size mapping for spinner const sizeClasses = { sm: 'h-4 w-4 border-2', md: 'h-8 w-8 border-2', lg: 'h-12 w-12 border-3', xl: 'h-16 w-16 border-4', }; // Color mapping for spinner const colorClasses = { primary: 'border-blue-600 border-t-transparent', white: 'border-white border-t-transparent', gray: 'border-gray-400 border-t-transparent', }; // Text size mapping const textSizeClasses = { sm: 'text-sm', md: 'text-base', lg: 'text-lg', xl: 'text-xl', }; export function LoadingSpinner({ size = 'md', color = 'primary', message, fullScreen = false, className, }: LoadingSpinnerProps) { const spinner = (
); if (fullScreen) { return (
{spinner} {message && (

{message}

)}
); } if (message) { return (
{spinner}

{message}

); } return spinner; } /** * LoadingOverlay - Full-screen loading overlay with backdrop * * @example * ```tsx * {isLoading && ( * * )} * ``` */ interface LoadingOverlayProps { message?: string; backdrop?: 'light' | 'dark' | 'blur'; } export function LoadingOverlay({ message = 'Loading...', backdrop = 'blur' }: LoadingOverlayProps) { const backdropClasses = { light: 'bg-white/80', dark: 'bg-slate-900/80', blur: 'bg-white/80 backdrop-blur-sm', }; return (

{message}

); } /** * InlineLoader - Small inline loading indicator * * @example * ```tsx * * ``` */ interface InlineLoaderProps { className?: string; } export function InlineLoader({ className }: InlineLoaderProps) { return ( ); } /** * PageLoader - Full page loading state with centered spinner * * @example * ```tsx * if (isLoading) return ; * ``` */ interface PageLoaderProps { message?: string; } export function PageLoader({ message }: PageLoaderProps) { return (
{message && (

{message}

)}
); }