# Spinner

A turning arc that shows work is running when the amount is unknown: loading a list, checking a value. Its name is read by screen readers and never shown.

## Usage

### When to use

- Show that work runs when its length is unknown: loading comments, checking a value.
- A small region or a control that waits, right where the result will appear.

### When not to use

- Work whose amount is known, such as an upload. Use Progress.
- A page or list whose layout you know while it loads. Use Skeleton.

## Variants

### size

sm (16px) inside sm and md controls; md (20px) inside lg controls; lg (24px) on its own in a region that loads.

Values: `sm`, `md`, `lg`. Default: `md`.

### tone

secondary on surfaces; accent when the spinner is the main thing on screen; current takes the text color around it, such as a label inside a Button.

Values: `secondary`, `accent`, `current`. Default: `secondary`.

## Examples

### Loading a list

```tsx
<div className="flex items-center gap-sm text-sm text-text-secondary">
  <Spinner size="sm" label="Loading comments" />
  <span aria-hidden="true">Loading comments</span>
</div>
```

### On its own

lg and accent when it is the only thing in the region.

```tsx
<Spinner size="lg" tone="accent" label="Loading dashboard" />
```

## Do and don't

### Do

- Name what loads in the label: Loading comments.
- Put it where the content will appear, so the eye is already there when it does.
- Use tone current inside a control, so it takes the control's text color.

### Don't

- Don't use it when the amount of work is known, such as an upload. Use Progress.
- Don't use it for a whole page or list whose layout you know. Use Skeleton.
- Don't show several spinners for one task.

## Props

| Name | Type | Values | Default | Description |
| --- | --- | --- | --- | --- |
| `size` | `enum` | `sm`, `md`, `lg` | `md` | sm (16px) inside sm and md controls; md (20px) inside lg controls; lg (24px) on its own in a region that loads. |
| `tone` | `enum` | `secondary`, `accent`, `current` | `secondary` | secondary on surfaces; accent when the spinner is the main thing on screen; current takes the text color around it, such as a label inside a Button. |
| `label` | `string` |  | `Loading` | What is loading, for screen readers: Loading comments. Never shown. |

## Anatomy

| Part | Description |
| --- | --- |
| `root` | An inline box the size of the icon, in an icon color. |
| `icon` | Tabler Loader2: 16px (sm), 20px (md) or 24px (lg). It turns under motion-safe. |
| `label` | Visually hidden text that names what is loading. |

## Accessibility

Role: `status`

- The root is a status region, and label (Loading by default) is its visually hidden text. Name what loads: Loading comments.
- The arc is decorative (aria-hidden); the label carries the meaning.
- It turns only when the user allows motion. Under prefers-reduced-motion it holds still, and the label still says what is happening.
- Remove it when the work is done, and move focus to the result only if the user asked for it.

## Install

```bash
npx shadcn add https://werewolf-ui.vercel.app/r/spinner.json
```

This also adds `styles/werewolf.css`, the tokens every component uses, and any other component it needs. Import that file once in your root CSS, after `@import "tailwindcss"`, with a path relative to that CSS file (from `app/globals.css` it is `@import "../styles/werewolf.css"`).
