Back to skills
SkillHub ClubDesign ProductFull StackData / AIDesigner

ai-loading-ux

Design AI loading, thinking, and progress indicator UX. Use when explicitly asked to improve AI waiting states, add thinking indicators, or design loading UX for AI interfaces. Covers reasoning display (chain-of-thought), progress steps, streaming states, and the "elevator mirror effect" for reducing perceived wait time.

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
19
Hot score
87
Updated
March 20, 2026
Overall rating
C2.2
Composite score
2.2
Best-practice grade
B72.0

Install command

npx @skill-hub/cli install rohunvora-cool-claude-skills-ai-loading-ux

Repository

rohunvora/cool-claude-skills

Skill path: skills/ai-loading-ux

Design AI loading, thinking, and progress indicator UX. Use when explicitly asked to improve AI waiting states, add thinking indicators, or design loading UX for AI interfaces. Covers reasoning display (chain-of-thought), progress steps, streaming states, and the "elevator mirror effect" for reducing perceived wait time.

Open repository

Best for

Primary workflow: Design Product.

Technical facets: Full Stack, Data / AI, Designer.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: rohunvora.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install ai-loading-ux into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/rohunvora/cool-claude-skills before adding ai-loading-ux to shared team environments
  • Use ai-loading-ux for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: ai-loading-ux
description: Design AI loading, thinking, and progress indicator UX. Use when explicitly asked to improve AI waiting states, add thinking indicators, or design loading UX for AI interfaces. Covers reasoning display (chain-of-thought), progress steps, streaming states, and the "elevator mirror effect" for reducing perceived wait time.
---

# AI Loading UX

Design patterns for showing users what's happening while waiting for AI output.

## Decision Framework

First, identify which pattern category applies:

| User is waiting for... | Pattern Category | Key Goal |
|------------------------|------------------|----------|
| AI reasoning/thinking | **Reasoning Display** | Build trust through transparency |
| Multi-step task completion | **Progress Steps** | Show advancement toward goal |
| Content generation/streaming | **Streaming States** | Reduce perceived wait time |
| Background processing | **Status Indicators** | Confirm work is happening |

## Core Principles

### 1. The Elevator Mirror Effect
Users waiting for AI feel time pass slower. Give them something to watch/read—animated indicators reduce *perceived* wait time even when actual time is unchanged.

### 2. Progressive Disclosure
- Show condensed indicator by default ("Thinking...")
- Make details *available* but not forced
- Let curious users expand; don't burden everyone

### 3. More Transparency ≠ Better UX
Balance visibility with cognitive load. Users want answers, not reasoning—but they want to *trust* the answer came from good reasoning.

### 4. Signal Completion Clearly
Users must know when processing ends. Ambiguous end states frustrate users.

## Pattern Quick Reference

### Reasoning Display (Chain-of-Thought)
When AI is "thinking" through a problem. See [references/reasoning-patterns.md](references/reasoning-patterns.md).

**Best approach (Claude-style):**
- Hidden by default, expandable on demand
- Structured bullets when expanded
- Time counter or progress indicator
- Clear "done" state

**Anti-patterns:**
- Wall of streaming text (overwhelming)
- Scrolling too fast to read
- No expand option (feels opaque)
- No clear end state

### Progress Steps
When AI completes sequential tasks. See [references/progress-patterns.md](references/progress-patterns.md).

**Best approach:**
- Show current step + total steps
- Mark completed steps visually
- Show what's actively happening
- Allow step-level details on expand

### Streaming States
When content generates token-by-token. See [references/streaming-patterns.md](references/streaming-patterns.md).

**Best approach:**
- Typing cursor or text animation
- Smooth token appearance (not jarring)
- Skeleton for expected content shape
- "Stop generating" escape hatch

### Status Indicators
When background work happens. See [references/status-patterns.md](references/status-patterns.md).

**Best approach:**
- Subtle but visible animation
- Brief description of current action
- Don't block user from other actions
- Notify on completion

## Implementation Checklist

When implementing any AI loading state:

1. [ ] **Identify pattern category** from decision framework above
2. [ ] **Choose visibility level**: always visible, expandable, or minimal
3. [ ] **Add motion**: animation reduces perceived wait (but keep it subtle)
4. [ ] **Show progress**: time elapsed, steps completed, or content streamed
5. [ ] **Signal completion**: clear visual/state change when done
6. [ ] **Provide escape**: stop/cancel for long operations
7. [ ] **Handle errors**: don't leave user in permanent loading state
8. [ ] **Test on slow connections**: ensure graceful degradation

## Product Comparisons (Reference)

| Product | Approach | Strength | Weakness |
|---------|----------|----------|----------|
| Claude | Hidden reasoning, expandable, structured bullets | Low cognitive load | Can feel opaque |
| ChatGPT | Brief labels, auto-collapse | Unobtrusive | Less transparent |
| DeepSeek | Full streaming reasoning | Maximum transparency | Overwhelming |
| Gemini | User-scrolled, numbered steps | Clear structure | Unclear completion |

## Usage

Read the relevant reference file for your pattern category:
- [references/reasoning-patterns.md](references/reasoning-patterns.md) - Chain-of-thought, thinking indicators
- [references/progress-patterns.md](references/progress-patterns.md) - Step sequences, task completion
- [references/streaming-patterns.md](references/streaming-patterns.md) - Token streaming, content generation
- [references/status-patterns.md](references/status-patterns.md) - Background processing, polling states


---

## Referenced Files

> The following files are referenced in this skill and included for context.

### references/reasoning-patterns.md

```markdown
# Reasoning Display Patterns

For AI interfaces that show chain-of-thought or "thinking" processes.

## Table of Contents
- [When to Use](#when-to-use)
- [Anatomy of a Thinking Indicator](#anatomy-of-a-thinking-indicator)
- [Visibility Levels](#visibility-levels)
- [State Machine](#state-machine)
- [Implementation Patterns](#implementation-patterns)
- [Accessibility](#accessibility)

## When to Use

Use reasoning display when:
- AI is solving complex problems (math, logic, planning)
- Users benefit from understanding *how* the answer was reached
- Trust-building is important (financial, medical, legal domains)
- The process takes >3 seconds

Skip reasoning display when:
- Simple Q&A or lookups
- Speed is more important than transparency
- Content speaks for itself (creative writing, summaries)

## Anatomy of a Thinking Indicator

```
┌─────────────────────────────────────────┐
│ 🧠 Thinking...                    12s   │  ← Header: icon + label + timer
├─────────────────────────────────────────┤
│ ▸ Analyzing the problem                 │  ← Expandable reasoning steps
│ ▸ Considering edge cases                │
│ • Checking mathematical constraints     │  ← Current step (animated)
└─────────────────────────────────────────┘
```

**Components:**
1. **Icon** - Animated to show activity (brain, sparkles, dots)
2. **Label** - Changes based on phase ("Thinking...", "Analyzing...", "Finalizing...")
3. **Timer** - Elapsed time (reduces anxiety about stuck states)
4. **Reasoning list** - Structured bullets, progressive reveal
5. **Expand/collapse** - User control over detail level

## Visibility Levels

### Level 1: Minimal (ChatGPT-style)
```
Thinking...
```
- Just a label + animation
- Collapses when done
- Best for: Fast responses, simple queries

### Level 2: Summary (Claude-style)
```
▼ Thinking (8s)
  • Analyzing request
  • Searching knowledge
  • Formulating response
```
- Collapsed by default, expandable
- Shows high-level steps
- Best for: Balance of transparency and simplicity

### Level 3: Verbose (DeepSeek-style)
```
Thinking...
First, I need to understand what the user is asking.
They want to know about X, which involves Y and Z.
Let me consider the implications...
[continues streaming]
```
- Full reasoning visible
- Streams in real-time
- Best for: Power users, debugging, research contexts

## State Machine

```
┌─────────┐    start    ┌──────────┐   complete   ┌──────────┐
│  Idle   │ ─────────→  │ Thinking │  ─────────→  │   Done   │
└─────────┘             └──────────┘              └──────────┘
                              │                        │
                              │ error                  │ dismiss
                              ▼                        ▼
                        ┌──────────┐              ┌──────────┐
                        │  Error   │              │  Hidden  │
                        └──────────┘              └──────────┘
```

**State behaviors:**
- **Idle**: No indicator visible
- **Thinking**: Animated indicator, timer counting, steps appearing
- **Done**: Animation stops, checkmark or fade, then transition to answer
- **Error**: Red state, error message, retry option
- **Hidden**: Collapsed but accessible via "Show thinking"

## Implementation Patterns

### Pattern A: Collapsible Accordion
```
// Pseudocode - adapt to your framework

ThinkingIndicator:
  state: collapsed | expanded
  steps: string[]
  currentStep: number
  elapsedTime: number

  render:
    if collapsed:
      <Row onClick={expand}>
        <AnimatedIcon />
        <Label>"Thinking..."</Label>
        <Timer>{elapsedTime}s</Timer>
        <ChevronDown />
      </Row>

    if expanded:
      <Column>
        <Header onClick={collapse}>
          <AnimatedIcon />
          <Label>"Thinking..."</Label>
          <Timer>{elapsedTime}s</Timer>
          <ChevronUp />
        </Header>
        <StepList>
          {steps.map((step, i) =>
            <Step
              complete={i < currentStep}
              active={i === currentStep}
            >
              {step}
            </Step>
          )}
        </StepList>
      </Column>
```

### Pattern B: Inline Badge
```
// For chat interfaces where thinking appears inline

<Message>
  <ThinkingBadge status={thinking ? "active" : "complete"}>
    {thinking ? "Thinking..." : `Thought for ${time}s`}
  </ThinkingBadge>
  {!thinking && <Content>{response}</Content>}
</Message>
```

### Pattern C: Side Panel
```
// For complex reasoning that shouldn't interrupt main flow

<Layout>
  <MainContent>
    {response}
  </MainContent>
  <SidePanel visible={showReasoning}>
    <ReasoningTrace steps={steps} />
  </SidePanel>
</Layout>
```

## Accessibility

- **Screen readers**: Announce state changes ("Now thinking", "Response ready")
- **Reduced motion**: Replace animations with static indicators
- **Keyboard**: Expand/collapse with Enter/Space
- **Color**: Don't rely on color alone for state (use icons too)

## Common Mistakes

1. **No end state** - Users don't know thinking finished
2. **Too verbose** - Reasoning overwhelms the answer
3. **No escape** - Can't stop or skip long thinking
4. **Frozen UI** - Blocking interaction during thinking
5. **Lost on error** - No recovery path when thinking fails

```

### references/progress-patterns.md

```markdown
# Progress Step Patterns

For AI interfaces that complete multi-step tasks.

## Table of Contents
- [When to Use](#when-to-use)
- [Anatomy of Progress Steps](#anatomy-of-progress-steps)
- [Step States](#step-states)
- [Layout Patterns](#layout-patterns)
- [Implementation Patterns](#implementation-patterns)
- [Edge Cases](#edge-cases)

## When to Use

Use progress steps when:
- Task has 3+ discrete steps
- Steps complete sequentially
- Users need to know what's happening at each stage
- Total time exceeds 10 seconds

Examples:
- "Analyzing document → Extracting data → Formatting report"
- "Searching → Filtering → Ranking → Generating response"
- "Uploading → Processing → Saving"

## Anatomy of Progress Steps

```
┌─────────────────────────────────────────────────────┐
│  Processing your request                            │
│  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━░░░░░░░░  75%     │
├─────────────────────────────────────────────────────┤
│  ✓ Analyzing document              2.3s            │
│  ✓ Extracting key information      4.1s            │
│  ● Generating summary...           1.2s            │
│  ○ Formatting output                               │
└─────────────────────────────────────────────────────┘
```

**Components:**
1. **Header** - Overall task description
2. **Progress bar** - Visual completion indicator
3. **Step list** - Individual steps with status
4. **Timing** - Per-step or total elapsed time

## Step States

| State | Visual | Behavior |
|-------|--------|----------|
| Pending | ○ (empty circle) | Grayed out, waiting |
| Active | ● (filled, pulsing) | Highlighted, animated |
| Complete | ✓ (checkmark) | Green, shows duration |
| Error | ✗ (x mark) | Red, shows error message |
| Skipped | — (dash) | Gray, strikethrough |

## Layout Patterns

### Vertical List (Default)
```
✓ Step 1: Completed
● Step 2: In progress...
○ Step 3: Pending
○ Step 4: Pending
```
Best for: 3-7 steps, detailed descriptions

### Horizontal Stepper
```
[1]───[2]───[3]───[4]
 ✓     ●     ○     ○
```
Best for: 3-5 steps, compact UI, wizards

### Compact Badge
```
Step 2 of 4: Processing...
```
Best for: Minimal UI, mobile, inline display

### Timeline
```
2:00 PM ─● Started analysis
2:01 PM ─✓ Extracted 234 records
2:02 PM ─● Generating report...
         ○ Finalizing
```
Best for: Audit trails, long-running tasks

## Implementation Patterns

### Pattern A: Linear Steps with Substeps
```
// Pseudocode

ProgressSteps:
  steps: Step[]
  currentStep: number

  Step:
    label: string
    status: pending | active | complete | error
    substeps?: string[]
    duration?: number

  render:
    <Container>
      <ProgressBar percent={currentStep / steps.length * 100} />
      <StepList>
        {steps.map((step, i) =>
          <StepRow status={step.status}>
            <StatusIcon status={step.status} />
            <Label>{step.label}</Label>
            {step.duration && <Duration>{step.duration}s</Duration>}
            {step.status === "active" && step.substeps && (
              <Substeps>
                {step.substeps.map(sub => <SubstepRow>{sub}</SubstepRow>)}
              </Substeps>
            )}
          </StepRow>
        )}
      </StepList>
    </Container>
```

### Pattern B: Streaming Steps
```
// Steps appear as they're discovered (not predetermined)

StreamingProgress:
  steps: Step[] = []

  onNewStep(step):
    steps.push(step)

  onStepComplete(stepId):
    steps.find(s => s.id === stepId).status = "complete"

  render:
    <Container>
      {steps.map(step => <StepRow {...step} />)}
      {isProcessing && <PendingIndicator />}
    </Container>
```

### Pattern C: Action Plan Preview
```
// Show planned steps before execution (builds trust)

ActionPlan:
  plannedSteps: string[]
  executedSteps: Step[]

  render:
    <Container>
      <Header>I'll do the following:</Header>
      {plannedSteps.map((step, i) => {
        const executed = executedSteps[i]
        return (
          <StepRow
            status={executed?.status || "pending"}
            label={step}
            actual={executed?.label} // May differ from planned
          />
        )
      })}
    </Container>
```

## Edge Cases

### Unknown Step Count
When you don't know how many steps upfront:
```
Processing... (Step 3)
✓ Analyzed structure
✓ Extracted entities
● Resolving references...
```
- Show completed count, not percentage
- Add "..." to indicate more may come

### Step Failure with Recovery
```
✓ Step 1: Complete
✗ Step 2: Failed - Retrying (attempt 2/3)
○ Step 3: Waiting
```
- Show retry status
- Don't reset the whole progress
- Offer skip option for non-critical steps

### Parallel Steps
```
● Processing (3 tasks running)
  ├─ ● Analyzing images (12/50)
  ├─ ● Extracting text (34/50)
  └─ ● Classifying content (8/50)
```
- Show each parallel task's progress
- Complete parent when all children complete

### Long-Running Steps
```
● Generating report... (2m 34s)
  Last update: Processing section 4 of 12

  [Show Details] [Cancel]
```
- Provide sub-progress or last action
- Always offer cancel for long steps
- Consider timeout warnings

## Accessibility

- Use `aria-live="polite"` for step announcements
- Progress bar needs `role="progressbar"` with `aria-valuenow`
- Ensure color isn't only indicator (icons matter)
- Support keyboard navigation between steps

```

### references/streaming-patterns.md

```markdown
# Streaming Content Patterns

For AI interfaces that display content as it generates token-by-token.

## Table of Contents
- [When to Use](#when-to-use)
- [Streaming Behaviors](#streaming-behaviors)
- [Visual Indicators](#visual-indicators)
- [Implementation Patterns](#implementation-patterns)
- [Performance Considerations](#performance-considerations)
- [Edge Cases](#edge-cases)

## When to Use

Use streaming display when:
- Content generates incrementally (LLM token streaming)
- Showing progress reduces perceived wait time
- Users can start reading before generation completes
- Response length is unpredictable

Skip streaming when:
- Response is very short (<50 tokens)
- Content needs validation before display
- Structured output must be complete to render (JSON, tables)

## Streaming Behaviors

### Text Streaming
```
The quick brown fox jum|
The quick brown fox jumps over|
The quick brown fox jumps over the lazy dog.|
```
- Append tokens as received
- Cursor indicates active generation

### Block Streaming
```
┌──────────────────────────┐
│ Generating...            │
│ ████████░░░░░░░░ 50%     │
└──────────────────────────┘
         ↓
┌──────────────────────────┐
│ Here is your summary:    │
│                          │
│ The document discusses...│
└──────────────────────────┘
```
- Show placeholder until enough content
- Reveal in chunks for smoother reading

### Skeleton → Content
```
┌──────────────────────────┐     ┌──────────────────────────┐
│ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ │     │ Introduction             │
│ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓       │  →  │ This report covers...    │
│ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓    │     │ Key findings include:    │
└──────────────────────────┘     └──────────────────────────┘
```
- Pre-render expected shape
- Replace skeleton with real content
- Reduces layout shift

## Visual Indicators

### Cursor Styles
```
█  Block cursor (classic terminal)
|  Line cursor (text editor)
●  Dot cursor (minimal)
▋  Half-block cursor (modern)
```

### Animation States
- **Typing**: Cursor visible, blinking or solid
- **Paused**: Cursor visible, no blink, "paused" indicator
- **Complete**: Cursor hidden, content stable
- **Error**: Red indicator, error message appended

### Container Indicators
```
┌─ Generating ─────────────────┐
│ Content streams here...      │
│                          ... │ ← Activity dots
└──────────────────────────────┘
```

## Implementation Patterns

### Pattern A: Simple Token Append
```
// Pseudocode

StreamingText:
  content: string = ""
  isGenerating: boolean = false

  onToken(token):
    content += token

  render:
    <Container>
      <Text>{content}</Text>
      {isGenerating && <Cursor />}
    </Container>
```

### Pattern B: Smooth Token Rendering
```
// Batch tokens to reduce render frequency

StreamingText:
  displayContent: string = ""
  buffer: string = ""

  onToken(token):
    buffer += token

  // Flush buffer on interval (e.g., 50ms) or buffer size
  flushBuffer():
    displayContent += buffer
    buffer = ""

  render:
    <Container>
      <Text>{displayContent}</Text>
      {isGenerating && <Cursor />}
    </Container>
```

### Pattern C: Markdown Streaming
```
// Handle markdown as it streams

MarkdownStream:
  rawContent: string = ""

  onToken(token):
    rawContent += token

  render:
    // Parse complete markdown blocks, hold incomplete ones
    const { complete, partial } = parseMarkdown(rawContent)

    <Container>
      <Markdown>{complete}</Markdown>
      <RawText>{partial}</RawText>
      {isGenerating && <Cursor />}
    </Container>
```

### Pattern D: Code Block Streaming
```
// Special handling for code blocks

CodeStream:
  content: string = ""
  inCodeBlock: boolean = false

  onToken(token):
    content += token
    inCodeBlock = detectCodeBlock(content)

  render:
    if inCodeBlock:
      <CodeEditor
        value={content}
        language={detectLanguage(content)}
        streaming={true}
      />
    else:
      <Text>{content}</Text>
```

## Performance Considerations

### Token Batching
Don't render on every single token—batch updates:
```
// Bad: renders 100 times for 100 tokens
tokens.forEach(token => setContent(c => c + token))

// Good: batches into ~20 renders
const BATCH_INTERVAL = 50 // ms
let batch = ""
tokens.forEach(token => batch += token)
setInterval(() => {
  if (batch) {
    setContent(c => c + batch)
    batch = ""
  }
}, BATCH_INTERVAL)
```

### Virtual Scrolling
For very long outputs:
```
// Only render visible portion
<VirtualList
  items={contentLines}
  renderItem={(line) => <Line>{line}</Line>}
  autoScroll={isGenerating}
/>
```

### Debounced Parsing
For rich content (markdown, code highlighting):
```
// Don't re-parse on every token
const parsedContent = useDebouncedMemo(
  () => parseMarkdown(rawContent),
  [rawContent],
  100 // ms
)
```

## Edge Cases

### Stop Generation
```
<Container>
  <StreamingContent content={content} />
  {isGenerating && (
    <StopButton onClick={stop}>
      ■ Stop generating
    </StopButton>
  )}
</Container>
```
- Always provide escape hatch
- Clearly indicate what will happen (content preserved)

### Connection Loss
```
<Container>
  <Text>{content}</Text>
  {connectionLost && (
    <Warning>
      Connection lost.
      <Button onClick={resume}>Resume</Button>
      <Button onClick={retry}>Retry from start</Button>
    </Warning>
  )}
</Container>
```
- Preserve partial content
- Offer resume if possible

### Rate Limiting
```
<Container>
  <Text>{content}</Text>
  {rateLimited && (
    <Notice>
      Slowing down... will continue in {countdown}s
    </Notice>
  )}
</Container>
```
- Don't lose content on rate limit
- Show clear status and countdown

### Empty Response
```
if (isComplete && !content) {
  <EmptyState>
    No response generated. This might mean:
    • The query was too vague
    • Content was filtered
    <Button onClick={retry}>Try again</Button>
  </EmptyState>
}
```

## Accessibility

- Announce streaming start: "Generating response"
- Announce completion: "Response complete"
- Don't auto-scroll aggressively (disorienting for screen readers)
- Provide "skip to end" option for long streams
- Ensure stop button is keyboard accessible

```

### references/status-patterns.md

```markdown
# Status Indicator Patterns

For AI interfaces with background processing or polling states.

## Table of Contents
- [When to Use](#when-to-use)
- [Indicator Types](#indicator-types)
- [Placement Strategies](#placement-strategies)
- [Implementation Patterns](#implementation-patterns)
- [Notification Patterns](#notification-patterns)
- [Edge Cases](#edge-cases)

## When to Use

Use status indicators when:
- Work happens in the background
- User can continue other tasks while waiting
- Process duration is unpredictable
- User needs awareness without blocking interaction

Examples:
- "Syncing your data..."
- "Indexing files in background"
- "Waiting for API response"
- "Training model (this may take a while)"

## Indicator Types

### Spinner / Loader
```
⟳ Processing...
```
- Simple, universally understood
- No progress information
- Best for: Unknown duration, quick tasks

### Pulsing Dot
```
● Syncing
```
- Subtle, non-intrusive
- Shows activity without demanding attention
- Best for: Ambient background status

### Progress Ring / Bar
```
◐ 45% complete
━━━━━━━━░░░░░░░░
```
- Shows measurable progress
- Best for: Known duration/size, file uploads

### Status Badge
```
[Processing] Document.pdf
```
- Inline with content
- Best for: Per-item status in lists

### Toast / Banner
```
┌──────────────────────────────────┐
│ ● Background sync in progress... │
└──────────────────────────────────┘
```
- Temporary, dismissible
- Best for: Temporary states, notifications

## Placement Strategies

### Global Status Bar
```
┌────────────────────────────────────────┐
│  App Header                    ● Sync  │ ← Top-right badge
├────────────────────────────────────────┤
│                                        │
│  Main Content                          │
│                                        │
└────────────────────────────────────────┘
```
- Always visible
- Doesn't interrupt flow
- Click to expand details

### Contextual Inline
```
┌─ Files ────────────────────────────────┐
│  📄 Report.pdf           ✓ Ready       │
│  📄 Analysis.xlsx        ⟳ Processing  │ ← Per-item status
│  📄 Summary.doc          ✓ Ready       │
└────────────────────────────────────────┘
```
- Status next to affected item
- Clear relationship
- Good for lists/tables

### Floating Indicator
```
                    ┌───────────────────┐
                    │ ● 3 tasks running │
                    │   View details →  │
                    └───────────────────┘
Main Content
```
- Doesn't take layout space
- Can be minimized
- Good for non-blocking background tasks

### Full-Screen Overlay (Use Sparingly)
```
┌────────────────────────────────────────┐
│                                        │
│         ⟳ Preparing workspace...       │
│                                        │
│         This may take a minute         │
│                                        │
└────────────────────────────────────────┘
```
- Blocks interaction
- Only for critical initialization
- Must have timeout/escape

## Implementation Patterns

### Pattern A: Background Task Manager
```
// Pseudocode

TaskManager:
  tasks: Task[] = []

  Task:
    id: string
    label: string
    status: pending | running | complete | error
    progress?: number

  addTask(task):
    tasks.push(task)

  updateTask(id, updates):
    tasks.find(t => t.id === id).merge(updates)

  render:
    <FloatingPanel>
      <Header>
        {runningCount} task(s) running
        <CollapseButton />
      </Header>
      {expanded && (
        <TaskList>
          {tasks.map(task => (
            <TaskRow status={task.status}>
              <Label>{task.label}</Label>
              {task.progress && <ProgressBar value={task.progress} />}
              {task.status === "error" && <RetryButton />}
            </TaskRow>
          ))}
        </TaskList>
      )}
    </FloatingPanel>
```

### Pattern B: Polling Status
```
// For async operations that require polling

PollingStatus:
  status: idle | polling | success | error
  lastCheck: timestamp

  startPolling(interval = 2000):
    status = "polling"
    poll()

  poll():
    result = await checkStatus()
    lastCheck = now()

    if result.complete:
      status = "success"
      onComplete(result)
    else if result.error:
      status = "error"
    else:
      setTimeout(poll, interval)

  render:
    switch status:
      case "polling":
        <Badge>
          <Spinner />
          Checking... (last: {timeAgo(lastCheck)})
        </Badge>
      case "success":
        <Badge success>Complete</Badge>
      case "error":
        <Badge error>
          Failed <RetryButton onClick={startPolling} />
        </Badge>
```

### Pattern C: Optimistic UI with Background Sync
```
// Show immediate feedback, sync in background

OptimisticAction:
  localState: any
  syncStatus: synced | syncing | error

  performAction(action):
    // Update UI immediately
    localState = applyAction(localState, action)
    syncStatus = "syncing"

    // Sync in background
    try:
      await syncToServer(action)
      syncStatus = "synced"
    catch:
      syncStatus = "error"
      // Optionally revert localState

  render:
    <Container>
      <Content data={localState} />
      <SyncIndicator status={syncStatus} />
    </Container>
```

## Notification Patterns

### Completion Notifications
```
// When background task completes

onTaskComplete(task):
  if document.hidden:
    // User not looking - use system notification
    showSystemNotification(`${task.label} complete`)
  else if !taskPanelVisible:
    // User in app but not watching - use toast
    showToast(`${task.label} complete`, { action: "View" })
  else:
    // User watching - just update status
    updateTaskStatus(task.id, "complete")
```

### Error Notifications
```
// Errors need more attention than success

onTaskError(task, error):
  // Always show prominent error
  showToast({
    type: "error",
    title: `${task.label} failed`,
    message: error.message,
    actions: [
      { label: "Retry", onClick: () => retryTask(task) },
      { label: "Dismiss", onClick: () => dismissTask(task) }
    ],
    persistent: true  // Don't auto-dismiss errors
  })
```

## Edge Cases

### Multiple Concurrent Tasks
```
<StatusBar>
  {tasks.length === 1 ? (
    <SingleTaskView task={tasks[0]} />
  ) : (
    <MultiTaskSummary count={tasks.length} onClick={showDetails} />
  )}
</StatusBar>
```

### Stale Status
```
// Detect stuck states

if (task.status === "running" && now() - task.lastUpdate > STALE_THRESHOLD):
  <TaskRow>
    <Label>{task.label}</Label>
    <Warning>
      No updates for {timeAgo(task.lastUpdate)}
      <Button onClick={checkStatus}>Check</Button>
      <Button onClick={cancel}>Cancel</Button>
    </Warning>
  </TaskRow>
```

### Reconnection
```
// After connection loss

<ConnectionStatus>
  {isReconnecting && (
    <Banner>
      <Spinner /> Reconnecting...
    </Banner>
  )}
  {justReconnected && (
    <Banner success>
      ✓ Reconnected. Syncing {pendingChanges} changes...
    </Banner>
  )}
</ConnectionStatus>
```

### Long-Running Background Tasks
```
// Tasks that take minutes/hours

<LongTaskStatus task={task}>
  <Title>{task.label}</Title>
  <Progress value={task.progress} />
  <Estimate>~{task.estimatedRemaining} remaining</Estimate>

  <Options>
    <Checkbox checked={notifyOnComplete}>
      Notify me when complete
    </Checkbox>
    <Button onClick={runInBackground}>
      Continue in background
    </Button>
  </Options>
</LongTaskStatus>
```

## Accessibility

- Use `aria-live="polite"` for status updates
- `aria-busy="true"` on elements being processed
- Don't use only color to indicate status
- Ensure spinners have accessible labels
- Provide text alternatives for all indicators
- Allow users to pause/hide animations

```