All files / src/components/common LoadingSpinner.tsx

100% Statements 3/3
100% Branches 3/3
100% Functions 1/1
100% Lines 3/3

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80                                                                                                    2x         12x           12x                                    
import React from 'react';
 
/**
 * Props for LoadingSpinner component
 */
export interface LoadingSpinnerProps {
  /**
   * Size of the spinner
   * @default 'md'
   */
  size?: 'sm' | 'md' | 'lg';
  
  /**
   * Optional test ID for automated testing
   */
  testId?: string;
  
  /**
   * Optional CSS class name
   */
  className?: string;
}
 
/**
 * Loading spinner component for indicating loading states
 * 
 * ## Business Perspective
 * 
 * Provides consistent visual feedback during data loading operations,
 * improving user experience by clearly indicating that the application
 * is working on their request. 🔄
 * 
 * ## Technical Perspective
 * 
 * Reusable loading indicator component that maintains visual consistency
 * across all widgets and screens. Uses Tailwind CSS for styling with
 * support for different sizes.
 * 
 * @example
 * ```tsx
 * // Small spinner
 * <LoadingSpinner size="sm" />
 * 
 * // Default medium spinner
 * <LoadingSpinner />
 * 
 * // Large spinner with custom test ID
 * <LoadingSpinner size="lg" testId="widget-loader" />
 * ```
 */
export const LoadingSpinner: React.FC<LoadingSpinnerProps> = ({ 
  size = 'md',
  testId = 'loading-spinner',
  className = ''
}) => {
  const sizeClasses: Record<'sm' | 'md' | 'lg', string> = {
    sm: 'w-4 h-4 border-2',
    md: 'w-8 h-8 border-4',
    lg: 'w-12 h-12 border-4',
  };
 
  return (
    <div 
      className={`flex justify-center items-center p-4 ${className}`}
      data-testid={`${testId}-container`}
      role="status"
      aria-label="Loading"
    >
      <div 
        className={`${sizeClasses[size]} border-blue-200 dark:border-blue-800 border-t-blue-600 dark:border-t-blue-400 rounded-full animate-spin`}
        data-testid={testId}
        aria-hidden="true"
      />
      <span className="sr-only">Loading...</span>
    </div>
  );
};
 
export default LoadingSpinner;