# Spinner
URL: https://remocn.dev/docs/ui/components/spinner

A deterministic spinning arc — pure function of the Remotion frame

- Install: `npx shadcn@latest add @remocn/spinner`
- Vibe: clean
- Natural length: 120f @ 30fps

A **motion atom**: a looping animation that is a pure function of `useCurrentFrame()`. No states, no props to sequence — just a spinning arc that advances deterministically with the timeline. Safe in Remotion's headless per-frame renderer (no `Date`, `Math.random`, or `requestAnimationFrame`).

## Installation

```bash
npx shadcn@latest add @remocn/spinner
```

> **Note**
>
> `spinner` is also installed automatically when you install `button`, via `registryDependencies`.

## Usage

Minimal — inherits color from the surrounding text:

```tsx
import { Spinner } from "@/components/remocn/spinner";

export const Scene = () => <Spinner />;
```

Sized and colored explicitly:

```tsx
import { Spinner } from "@/components/remocn/spinner";

export const Scene = () => (
  <Spinner size={32} color="oklch(0.55 0.2 250)" speed={1.5} />
);
```

## How rotation works

```
rotation (deg) = frame × speed × 6
```

At 30 fps with `speed=1`, one full rotation takes 20 frames (2 frames per 12°). Increase `speed` to spin faster without changing the composition fps.

## Props

| Prop | Type | Default | Description |
|---|---|---|---|
| `size` | `number` | `20` | Width and height of the SVG in px. |
| `color` | `string` | `"currentColor"` | Stroke color. Defaults to currentColor so it inherits the surrounding text color. |
| `speed` | `number` | `1` | Scales the playhead. rotation = frame × speed × 6 (deg). speed=2 spins twice as fast. |
| `strokeWidth` | `number` | `2.5` | Arc stroke width in viewBox units (viewBox is 0 0 24 24). |
| `className` | `string` | — | Optional className passed to the SVG element. |

## Use when
- Showing a loading indicator inside a button after a click (hover → press → loading state).
- Adding an inline async-operation indicator to any scene without layout overhead.
- Composing with `skeleton` or `button` to illustrate a loading-state moment in a flow.

## Don't use when
- You need a full-width loading bar with a track — use `progress` instead.
- You need a shimmer placeholder block — use `skeleton-block` instead.
- The loading state resolves to real content — use `skeleton` for the crossfade (spinner has no loaded state).