Back to skills
SkillHub ClubShip Full StackFull Stack

loading-states

Handle loading states in the portal app using Flask loaders. Use when adding loading indicators to buttons, cards, pages, or any async operations.

Packaged view

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

Stars
3
Hot score
80
Updated
March 20, 2026
Overall rating
C0.8
Composite score
0.8
Best-practice grade
A92.4

Install command

npx @skill-hub/cli install legacy3-wowlab-loading-states

Repository

legacy3/wowlab

Skill path: .claude/skills/loading-states

Handle loading states in the portal app using Flask loaders. Use when adding loading indicators to buttons, cards, pages, or any async operations.

Open repository

Best for

Primary workflow: Ship Full Stack.

Technical facets: Full Stack.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: legacy3.

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

What it helps with

  • Install loading-states into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/legacy3/wowlab before adding loading-states to shared team environments
  • Use loading-states for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: loading-states
description: Handle loading states in the portal app using Flask loaders. Use when adding loading indicators to buttons, cards, pages, or any async operations.
---

# Loading States in Portal

The portal uses custom Flask loader components for all loading states. Never use `Loader2` from lucide-react or CSS `animate-spin`.

## Components

Import from `@/components/ui/loader` or `@/components/ui`:

| Component       | Use Case                                                    |
| --------------- | ----------------------------------------------------------- |
| `Loader`        | Centered loading for cards, panels                          |
| `InlineLoader`  | Inline loading in buttons, text, badges                     |
| `CardLoader`    | Full card loading with optional message                     |
| `PageLoader`    | Full page loading (rarely needed)                           |
| `OverlayLoader` | Overlay with blur for blocking interactions                 |
| `Button`        | Has built-in `loading` prop (from `@/components/ui/button`) |

## Variants

Both `Loader` and `InlineLoader` support variants:

| Variant             | Use When                                 |
| ------------------- | ---------------------------------------- |
| `loading` (default) | Fetching data, waiting for response      |
| `processing`        | Running computations, simulations, tests |
| `idle`              | Ready state with subtle animation        |

## Button Loading States

### Simple Button with Loading (recommended)

The `Button` component has a built-in `loading` prop:

```tsx
import { Button } from "@/components/ui/button";

<Button loading={isLoading} onClick={handleSave}>
  Save Changes
</Button>;
```

With loading text and loader placement:

```tsx
<Button loading={isLoading} loadingText="Saving..." loaderPlacement="end">
  Save
</Button>
```

Button loading props:

- `loading` - shows the loader and disables the button
- `loadingText` - text to show while loading (if omitted, children are hidden but preserved for width)
- `loaderPlacement` - "start" (default) or "end" for position when using loadingText

### Manual Control with InlineLoader

For cases where you need manual control (e.g., different icons, processing variant):

```tsx
import { InlineLoader } from "@/components/ui/loader";
import { Button } from "@/components/ui/button";
import { Save } from "lucide-react";

<Button disabled={isLoading}>
  {isLoading ? <InlineLoader /> : <Save />}
  Save
</Button>;
```

### Processing Button (simulations, tests)

```tsx
import { InlineLoader } from "@/components/ui/loader";

<Button disabled={isRunning}>
  {isRunning ? <InlineLoader variant="processing" /> : <Play />}
  Run Simulation
</Button>;
```

## Card/Panel Loading

### Inside a Card

```tsx
import { Loader } from "@/components/ui/loader";

{
  loading ? (
    <styled.div
      display="flex"
      alignItems="center"
      justifyContent="center"
      py="8"
    >
      <Loader size="sm" />
    </styled.div>
  ) : (
    <CardContent>...</CardContent>
  );
}
```

### CardLoader with Message

```tsx
import { CardLoader } from "@/components/ui/loader";

{
  loading && <CardLoader message="Loading data ..." />;
}
```

### Inline with Text

```tsx
import { InlineLoader } from "@/components/ui/loader";

<styled.div display="flex" alignItems="center" justifyContent="center" py="8">
  <InlineLoader />
  <styled.span ml="2" textStyle="sm" color="fg.muted">
    Loading coverage data...
  </styled.span>
</styled.div>;
```

## Status Indicators

### Active Job/Process

```tsx
import { InlineLoader } from "@/components/ui/loader";

{
  job.status === "running" ? (
    <InlineLoader variant="processing" />
  ) : (
    <CheckIcon />
  );
}
```

### In Links (name resolution)

```tsx
import { InlineLoader } from "@/components/ui/loader";

{
  isLoading && <InlineLoader css={{ opacity: 0.5 }} />;
}
```

## Sizes

`Loader` sizes (Panda CSS spacing tokens):

- `xs` - 16px (4 spacing units) - used by `InlineLoader`
- `sm` - 24px (6 spacing units)
- `md` - 48px (12 spacing units) - default
- `lg` - 64px (16 spacing units)
- `xl` - 96px (24 spacing units)

`InlineLoader` is just `Loader` with `size="xs"` (16px).

## Page Loading (loading.tsx)

For route-level loading, keep using Skeleton components in `loading.tsx` files - they provide structural hints. Don't use Loader for page-level loading.

```tsx
// app/feature/loading.tsx
import { FeatureSkeleton } from "@/components/feature";

export default function FeatureLoading() {
  return <FeatureSkeleton />;
}
```

## Decision Guide

1. **Button loading** → `Button` with `loading` prop (preferred) or `InlineLoader` for manual control
2. **Running simulation/test** → `InlineLoader variant="processing"`
3. **Card/panel data loading** → `Loader size="sm"` or `CardLoader`
4. **Active job indicator** → `InlineLoader variant="processing"`
5. **Inline status** → `InlineLoader`
6. **Page loading** → Skeleton components (not Loader)
loading-states | SkillHub