# Spinner (/docs/spinner)





`Spinner` is a self-contained SVG indicator. The strokes use `currentColor`, so when `color` is omitted it inherits the surrounding text color — that's how Button and ActionIcon embed it without extra plumbing. Pass a palette `color` for standalone use to route through the kit's slot vars.

Two non-palette values round out the prop: `"currentColor"` is the explicit, named form of the inherit behavior, and `"default"` paints the neutral high-contrast stroke that matches Button's `default` variant.

```tsx
import { Spinner } from '@42-central/ui-react/spinner';

<Spinner color="brand" size="lg" />
<Spinner label="Syncing" color="green" size="md" />
<Spinner color="default" size="lg" />        {/* matches Button's default variant */}
<Spinner color="currentColor" size="lg" />   {/* explicit inherit */}
```

## Playground [#playground]

<story.Playground />

## Inheritance vs explicit [#inheritance-vs-explicit]

When used inside a container that already drives text color and SVG size (Button / ActionIcon), omit both `color` and `size` — Spinner picks them up via CSS inheritance.

<Preview align="center" code="&#x22;<Button color=\&#x22;brand\&#x22; loading>Saving</Button>\n<Button color=\&#x22;green\&#x22; variant=\&#x22;light\&#x22; loading>Syncing</Button>\n<Button color=\&#x22;red\&#x22; variant=\&#x22;outline\&#x22; loading>Deleting</Button>&#x22;">
  <Button color="brand">
    Saving
  </Button>

  <Button color="green" variant="light">
    Syncing
  </Button>

  <Button color="red" variant="outline">
    Deleting
  </Button>
</Preview>

## Sizes [#sizes]

<Preview align="center" code="&#x22;<Spinner size=\&#x22;xs\&#x22; color=\&#x22;brand\&#x22; />\n<Spinner size=\&#x22;sm\&#x22; color=\&#x22;brand\&#x22; />\n<Spinner size=\&#x22;md\&#x22; color=\&#x22;brand\&#x22; />\n<Spinner size=\&#x22;lg\&#x22; color=\&#x22;brand\&#x22; />\n<Spinner size=\&#x22;xl\&#x22; color=\&#x22;brand\&#x22; />&#x22;">
  <Spinner size="xs" color="brand" />

  <Spinner size="sm" color="brand" />

  <Spinner size="md" color="brand" />

  <Spinner size="lg" color="brand" />

  <Spinner size="xl" color="brand" />
</Preview>

## Accessibility [#accessibility]

`label` controls the screen-reader announcement:

* **Default** (`label="Loading"`): emits `role="img"` + an `<svg><title>` — screen readers announce "Loading".
* **Custom**: pass any string for a more specific phrase (`"Syncing"`, `"Submitting form"`).
* **Decorative** (`label={null}`): marks the SVG `aria-hidden` and skips the title. Use when a parent already broadcasts the busy state (e.g. Button's `aria-busy="true"` covers any embedded spinner).

```tsx
<Spinner label="Syncing your library" color="green" />

{/* When the parent has aria-busy, mark the spinner decorative. */}
<Button loading>Saving</Button>
{/* Button internally renders <Spinner label={null} /> */}
```

## API [#api]

<TypeTable
  type="{
  size: {
    type: &#x22;'xs' | 'sm' | 'md' | 'lg' | 'xl'&#x22;,
    description: 'Explicit size. Omit to inherit from a parent\'s [&_svg]:size-* rule.',
  },
  color: {
    type: &#x22;'brand' | 'neutral' | 'red' | 'orange' | 'yellow' | 'green' | 'teal' | 'cyan' | 'blue' | 'purple' | 'pink' | 'default' | 'currentColor' | (string & {})&#x22;,
    description: &#x22;Palette via slot vars, or 'default' (matches Button's default variant) / 'currentColor' (explicit inherit). Omit to inherit currentColor.&#x22;,
  },
  label: {
    type: 'string | null',
    default: &#x22;'Loading'&#x22;,
    description: 'Screen-reader label. Set to null for decorative usage.',
  },
  testId: {
    type: 'string',
    description: 'Renders as `data-testid` on the underlying `<svg>`. See [Testing](/docs/testing).',
  },
}"
/>

All other props are forwarded to the underlying `<svg>`.
