# Loading Component

A versatile loading indicator component that provides visual feedback while data is being loaded. Supports multiple variants, sizes, and animation states with full accessibility compliance.

## Overview

The Loading component is designed to provide clear visual feedback during asynchronous operations. It prevents layout shifts and ensures users understand when content is being loaded.

## Features

- **Multiple Variants**: Spinner, progress bar, and pulse indicators
- **Size Options**: Small, medium, and large sizes
- **Animation Control**: Can be disabled for static states
- **Accessibility**: WCAG compliant with proper ARIA attributes
- **Design Token Integration**: Fully themed using design system tokens
- **Responsive**: Adapts to different screen sizes and contexts

## Installation

```typescript
import { LoadingComponent } from '@Crystal-Code-Labs/ccl-ui-components';

@Component({
  imports: [LoadingComponent],
  // ...
})
export class MyComponent {}
```

## Basic Usage

### Spinner Loading

```html
<!-- Basic spinner -->
<ccl-loading variant="spinner" size="md" label="Loading data"></ccl-loading>

<!-- Large spinner with custom label -->
<ccl-loading 
  variant="spinner" 
  size="lg" 
  label="Loading profile picture">
</ccl-loading>
```

### Progress Bar Loading

```html
<!-- Animated progress bar -->
<ccl-loading variant="bar" label="Uploading file..."></ccl-loading>

<!-- Static progress bar -->
<ccl-loading 
  variant="bar" 
  [animated]="false" 
  label="Processing complete">
</ccl-loading>
```

### Pulse Loading

```html
<!-- Animated pulse -->
<ccl-loading variant="pulse" size="md" label="Saving changes"></ccl-loading>

<!-- Small pulse -->
<ccl-loading variant="pulse" size="sm" label="Syncing"></ccl-loading>
```

## API Reference

### Inputs

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `variant` | `'spinner' \| 'bar' \| 'pulse'` | `'spinner'` | The visual style of the loading indicator |
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | The size of the loading indicator |
| `animated` | `boolean` | `true` | Whether the loading indicator should animate |
| `label` | `string` | `'Loading…'` | Accessible label for screen readers |

### Variants

#### Spinner
A circular rotating indicator, best for general loading states.

```html
<ccl-loading variant="spinner" size="md" label="Loading data"></ccl-loading>
```

**Visual Characteristics:**
- Circular border with rotating highlight
- Smooth continuous rotation
- Works well in buttons and small spaces

#### Progress Bar
A horizontal bar that fills and empties, ideal for file uploads or data processing.

```html
<ccl-loading variant="bar" label="Uploading file..."></ccl-loading>
```

**Visual Characteristics:**
- Horizontal bar with sliding animation
- Shows progress-like movement
- Good for longer operations

#### Pulse
Three dots that pulse in sequence, perfect for subtle loading states.

```html
<ccl-loading variant="pulse" size="md" label="Processing"></ccl-loading>
```

**Visual Characteristics:**
- Three dots with staggered pulsing
- Gentle, non-distracting animation
- Great for inline loading states

### Sizes

| Size | Description | Use Case |
|------|-------------|----------|
| `sm` | Small (1rem) | Inline text, small buttons |
| `md` | Medium (1.5rem) | General purpose, cards |
| `lg` | Large (2rem) | Page-level loading, modals |

```html
<!-- Size examples -->
<ccl-loading variant="spinner" size="sm" label="Small spinner"></ccl-loading>
<ccl-loading variant="spinner" size="md" label="Medium spinner"></ccl-loading>
<ccl-loading variant="spinner" size="lg" label="Large spinner"></ccl-loading>
```

### Animation Control

Control whether the loading indicator animates or remains static.

```html
<!-- Animated (default) -->
<ccl-loading variant="spinner" [animated]="true" label="Animated"></ccl-loading>

<!-- Static -->
<ccl-loading variant="spinner" [animated]="false" label="Static"></ccl-loading>
```

**When to use static:**
- When animations are disabled globally
- For accessibility (respects `prefers-reduced-motion`)
- In print media or static contexts

## Accessibility

The Loading component is fully accessible and follows WCAG guidelines:

### ARIA Attributes

- **`role="status"`**: Indicates the element provides status information
- **`aria-label`**: Describes the loading state to screen readers

```html
<ccl-loading 
  variant="spinner" 
  label="Loading user profile"
  aria-label="Loading user profile">
</ccl-loading>
```

### Screen Reader Support

Screen readers will announce the loading state using the provided label:

```html
<!-- Screen reader announces: "Loading profile picture" -->
<ccl-loading variant="spinner" label="Loading profile picture"></ccl-loading>

<!-- Screen reader announces: "Loading…" (default) -->
<ccl-loading variant="spinner"></ccl-loading>
```

### Reduced Motion Support

The component automatically respects the user's motion preferences:

```css
@media (prefers-reduced-motion: reduce) {
  .ccl-loading__spinner--animated,
  .ccl-loading__bar--animated,
  .ccl-loading__pulse--animated {
    animation: none;
  }
}
```

## Styling and Theming

### Design Tokens

The component uses design system tokens for consistent theming:

```css
.ccl-loading {
  /* Colors */
  --color-surface-muted: #e5e7eb;      /* Background color */
  --color-surface-highlight: #3b82f6;  /* Active color */
  
  /* Border radius */
  --radius-sm: 0.25rem;                /* Small radius */
  --radius-pill: 50%;                  /* Circular elements */
  
  /* Animation */
  --motion-duration-sm: 1s;            /* Animation duration */
  --motion-ease-in-out: ease-in-out;   /* Animation easing */
}
```

### Custom Styling

Override design tokens for custom theming:

```css
:root {
  --color-surface-highlight: #10b981;  /* Green highlight */
  --motion-duration-sm: 0.8s;          /* Faster animation */
}
```

### CSS Classes

The component generates semantic CSS classes:

```html
<!-- Generated classes -->
<div class="ccl-loading ccl-loading--spinner ccl-loading--md">
  <div class="ccl-loading__spinner ccl-loading__spinner--animated">
    <div class="ccl-loading__spinner-ring"></div>
  </div>
</div>
```

**Class Structure:**
- `.ccl-loading` - Base component class
- `.ccl-loading--{variant}` - Variant modifier (spinner, bar, pulse)
- `.ccl-loading--{size}` - Size modifier (sm, md, lg)
- `.ccl-loading--static` - Static state (no animation)
- `.ccl-loading__spinner` - Spinner-specific elements
- `.ccl-loading__bar` - Progress bar elements
- `.ccl-loading__pulse` - Pulse elements

## Common Patterns

### Button Loading States with @if

```html
<!-- Basic button with loading state -->
<button [disabled]="isLoading" class="ccl-btn ccl-btn--primary">
  @if (isLoading) {
    <ccl-loading 
      variant="spinner" 
      size="sm" 
      label="Saving">
    </ccl-loading>
  } @else {
    <span>Save Changes</span>
  }
</button>

<!-- Icon button with loading -->
<button [disabled]="isDeleting" class="ccl-btn ccl-btn--destructive">
  @if (isDeleting) {
    <ccl-loading 
      variant="spinner" 
      size="sm" 
      label="Deleting">
    </ccl-loading>
  } @else {
    <span>🗑️ Delete</span>
  }
</button>

<!-- Multiple buttons with different loading states -->
<div class="button-group">
  <button 
    [disabled]="isSaving" 
    class="ccl-btn ccl-btn--primary"
    (click)="save()">
    @if (isSaving) {
      <ccl-loading 
        variant="spinner" 
        size="sm" 
        label="Saving">
      </ccl-loading>
    } @else {
      <span>Save</span>
    }
  </button>
  
  <button 
    [disabled]="isPublishing" 
    class="ccl-btn ccl-btn--secondary"
    (click)="publish()">
    @if (isPublishing) {
      <ccl-loading 
        variant="pulse" 
        size="sm" 
        label="Publishing">
      </ccl-loading>
    } @else {
      <span>Publish</span>
    }
  </button>
</div>
```

### Page Loading Overlay with @if

```html
<!-- Full page loading overlay -->
@if (isPageLoading) {
  <div class="loading-overlay">
    <ccl-loading 
      variant="spinner" 
      size="lg" 
      label="Loading page content">
    </ccl-loading>
  </div>
}

<!-- Modal loading overlay -->
@if (isModalLoading) {
  <div class="modal-overlay">
    <div class="modal-content">
      <ccl-loading 
        variant="pulse" 
        size="md" 
        label="Loading modal content">
      </ccl-loading>
    </div>
  </div>
}

<!-- Section-specific loading -->
@if (isDashboardLoading) {
  <div class="dashboard-section">
    <ccl-loading 
      variant="spinner" 
      size="lg" 
      label="Loading dashboard">
    </ccl-loading>
  </div>
}
```

### Inline Loading States with @if

```html
<!-- Content area with conditional loading -->
<div class="content-section">
  <h3>Recent Activity</h3>
  
  @if (loadingActivity) {
    <ccl-loading 
      variant="pulse" 
      size="sm" 
      label="Loading activity">
    </ccl-loading>
  } @else if (!activityError) {
    <div class="activity-list">
      @for (activity of activities; track activity.id) {
        <div class="activity-item">
          {{ activity.description }}
        </div>
      }
    </div>
  } @else {
    <div class="error-message">
      Failed to load activity
    </div>
  }
</div>

<!-- List with loading state -->
<div class="user-list">
  <h4>Users</h4>
  
  @if (loadingUsers) {
    <ccl-loading 
      variant="spinner" 
      size="md" 
      label="Loading users">
    </ccl-loading>
  } @else {
    <div class="users">
      @for (user of users; track user.id) {
        <div class="user-card">
          {{ user.name }}
        </div>
      }
    </div>
  }
</div>

<!-- Form with loading state -->
@if (!isSubmitting) {
  <form class="user-form">
    <input type="text" placeholder="Name" [(ngModel)]="user.name">
    <button type="submit" (click)="submitForm()">Submit</button>
  </form>
} @else {
  <div class="form-loading">
    <ccl-loading 
      variant="bar" 
      label="Submitting form">
    </ccl-loading>
    <p>Please wait while we process your request...</p>
  </div>
}
```

### File Upload Progress with @if

```html
<!-- File upload with progress -->
<div class="upload-area">
  @if (isUploading) {
    <ccl-loading 
      variant="bar" 
      label="Uploading file...">
    </ccl-loading>
  } @else if (!uploadComplete) {
    <div class="upload-prompt">
      <input type="file" (change)="onFileSelect($event)">
      <p>Select a file to upload</p>
    </div>
  } @else {
    <div class="upload-success">
      <p>✅ File uploaded successfully!</p>
    </div>
  }
</div>

<!-- Multiple file uploads -->
<div class="multi-upload">
  @for (file of files; track file.id; let i = $index) {
    <div class="file-item">
      <span>{{ file.name }}</span>
      
      @if (file.uploading) {
        <ccl-loading 
          variant="pulse" 
          size="sm" 
          [label]="'Uploading ' + file.name">
        </ccl-loading>
      } @else if (file.complete) {
        <span class="success">✅</span>
      } @else if (file.error) {
        <span class="error">❌</span>
      }
    </div>
  }
</div>
```

### Data Table Loading with @if

```html
<!-- Table with loading state -->
<div class="data-table">
  <table>
    <thead>
      <tr>
        <th>Name</th>
        <th>Email</th>
        <th>Status</th>
      </tr>
    </thead>
    <tbody>
      @if (loadingData) {
        <tr>
          <td colspan="3" class="loading-cell">
            <ccl-loading 
              variant="pulse" 
              size="sm" 
              label="Loading table data">
            </ccl-loading>
          </td>
        </tr>
      } @else {
        @for (user of users; track user.id) {
          <tr>
            <td>{{ user.name }}</td>
            <td>{{ user.email }}</td>
            <td>{{ user.status }}</td>
          </tr>
        }
      }
    </tbody>
  </table>
</div>

<!-- Empty state with loading -->
<div class="table-container">
  @if (loadingData) {
    <ccl-loading 
      variant="spinner" 
      size="md" 
      label="Loading data">
    </ccl-loading>
  } @else if (users.length === 0) {
    <div class="empty-state">
      <p>No users found</p>
    </div>
  } @else {
    <div class="table-content">
      <!-- Table content here -->
    </div>
  }
</div>
```

### Search Results Loading with @if

```html
<!-- Search interface -->
<div class="search-container">
  <input 
    type="text" 
    placeholder="Search..." 
    [(ngModel)]="searchTerm"
    (input)="onSearch()">
  
  @if (isSearching) {
    <ccl-loading 
      variant="pulse" 
      size="sm" 
      label="Searching...">
    </ccl-loading>
  } @else if (searchResults.length > 0) {
    <div class="search-results">
      @for (result of searchResults; track result.id) {
        <div class="result-item">
          {{ result.title }}
        </div>
      }
    </div>
  } @else if (searchTerm) {
    <div class="no-results">
      <p>No results found for "{{ searchTerm }}"</p>
    </div>
  }
</div>
```

## Best Practices

### 1. Provide Meaningful Labels

Always provide descriptive labels for screen readers:

```html
<!-- Good -->
<ccl-loading variant="spinner" label="Loading user profile"></ccl-loading>

<!-- Avoid -->
<ccl-loading variant="spinner"></ccl-loading>
```

### 2. Choose Appropriate Variants

Select variants based on context:

- **Spinner**: General loading, buttons, small spaces
- **Progress Bar**: File uploads, data processing, longer operations
- **Pulse**: Subtle loading, inline content, non-intrusive states

### 3. Use Appropriate Sizes

Match size to context:

- **Small**: Inline text, buttons, compact layouts
- **Medium**: Cards, general content areas
- **Large**: Page-level loading, modals, prominent states

### 4. Handle Loading States Properly

Always provide fallback content and handle loading completion:

```html
<div class="content-area">
  @if (isLoading) {
    <ccl-loading 
      variant="spinner" 
      label="Loading content">
    </ccl-loading>
  } @else if (!error) {
    <div class="content">
      <!-- Loaded content -->
    </div>
  } @else {
    <div class="error">
      <!-- Error state -->
    </div>
  }
</div>
```

### 5. Respect User Preferences

The component automatically handles reduced motion preferences, but you can also provide manual control:

```html
<ccl-loading 
  variant="spinner" 
  [animated]="!userPrefersReducedMotion"
  label="Loading">
</ccl-loading>
```

## Troubleshooting

### Common Issues

**Loading indicator not showing:**
- Check that the component is imported
- Verify the variant is correctly specified
- Ensure the component is not hidden by CSS

**Animation not working:**
- Check if `animated` is set to `false`
- Verify CSS animations are not disabled globally
- Check for `prefers-reduced-motion` settings

**Accessibility issues:**
- Ensure meaningful labels are provided
- Test with screen readers
- Verify proper ARIA attributes are present

### Browser Support

The Loading component supports all modern browsers:

- Chrome 60+
- Firefox 55+
- Safari 12+
- Edge 79+

### Performance Considerations

- Animations use CSS transforms for optimal performance
- No JavaScript animations to avoid blocking the main thread
- Minimal DOM footprint for efficient rendering

## Migration Guide

### From Custom Loading Components

If migrating from custom loading implementations:

1. **Replace custom spinners:**
   ```html
   <!-- Before -->
   <div class="custom-spinner"></div>
   
   <!-- After -->
   <ccl-loading variant="spinner" size="md" label="Loading"></ccl-loading>
   ```

2. **Update progress indicators:**
   ```html
   <!-- Before -->
   <div class="progress-bar">
     <div class="progress-fill" [style.width.%]="progress"></div>
   </div>
   
   <!-- After -->
   <ccl-loading variant="bar" label="Processing"></ccl-loading>
   ```

3. **Add accessibility attributes:**
   ```html
   <!-- Before -->
   <div class="loading">Loading...</div>
   
   <!-- After -->
   <ccl-loading variant="spinner" label="Loading data"></ccl-loading>
   ```

## Examples

### Complete Loading States Example

```typescript
@Component({
  template: `
    <div class="app-container">
      <!-- Button with loading state -->
      <button 
        [disabled]="isSaving" 
        class="ccl-btn ccl-btn--primary"
        (click)="saveData()">
        @if (isSaving) {
          <ccl-loading 
            variant="spinner" 
            size="sm" 
            label="Saving">
          </ccl-loading>
        } @else {
          <span>Save Data</span>
        }
      </button>

      <!-- Content area with loading -->
      <div class="content-area">
        @if (isLoading) {
          <ccl-loading 
            variant="pulse" 
            size="md" 
            label="Loading content">
          </ccl-loading>
        } @else {
          <div class="content">
            <!-- Your content here -->
          </div>
        }
      </div>

      <!-- File upload progress -->
      @if (isUploading) {
        <div class="upload-area">
          <ccl-loading 
            variant="bar" 
            label="Uploading file...">
          </ccl-loading>
          <p>Uploading {{fileName}} ({{fileSize}})</p>
        </div>
      }
    </div>
  `
})
export class MyComponent {
  isSaving = false;
  isLoading = false;
  isUploading = false;
  fileName = '';
  fileSize = '';

  async saveData() {
    this.isSaving = true;
    try {
      await this.dataService.save();
    } finally {
      this.isSaving = false;
    }
  }
}
```

This comprehensive documentation covers all aspects of the Loading component, from basic usage to advanced patterns and troubleshooting. The component is now ready for production use with full accessibility support and design system integration.
