| import { cn } from '@/lib/utils'; | |
| import { HTMLAttributes } from 'react'; | |
| interface LoadingSpinnerProps extends HTMLAttributes<HTMLDivElement> { | |
| size?: 'sm' | 'md' | 'lg'; | |
| } | |
| /** | |
| * Loading spinner component with smooth animation. | |
| * | |
| * @param size - Size variant (default: md) | |
| * @param className - Additional CSS classes | |
| */ | |
| export function LoadingSpinner({ size = 'md', className, ...props }: LoadingSpinnerProps) { | |
| const sizeClasses = { | |
| sm: 'w-4 h-4 border-2', | |
| md: 'w-8 h-8 border-3', | |
| lg: 'w-12 h-12 border-4', | |
| }; | |
| return ( | |
| <div className={cn('flex items-center justify-center', className)} {...props}> | |
| <div | |
| className={cn( | |
| 'animate-spin rounded-full border-primary border-t-transparent', | |
| sizeClasses[size] | |
| )} | |
| role="status" | |
| aria-label="Loading" | |
| > | |
| <span className="sr-only">Loading...</span> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| /** | |
| * Full-page loading spinner with backdrop. | |
| */ | |
| export function FullPageLoadingSpinner() { | |
| return ( | |
| <div className="fixed inset-0 z-50 flex items-center justify-center bg-background/80 backdrop-blur-sm"> | |
| <LoadingSpinner size="lg" /> | |
| </div> | |
| ); | |
| } | |
| /** | |
| * Inline loading text with spinner. | |
| */ | |
| export function LoadingText({ text = 'Loading...' }: { text?: string }) { | |
| return ( | |
| <div className="flex items-center gap-2 text-muted-foreground"> | |
| <LoadingSpinner size="sm" /> | |
| <span className="text-sm">{text}</span> | |
| </div> | |
| ); | |
| } | |