# Spinner

> Loading indicator. Respects `prefers-reduced-motion`.

- Available in: `@sisyphos-ui/react`, `@sisyphos-ui/vue`, `@sisyphos-ui/angular`
- Docs: https://www.sisyphosui.com/docs/components/spinner

## Installation

Pick the framework binding that matches your stack:

```bash
pnpm add @sisyphos-ui/react   # React 18+
pnpm add @sisyphos-ui/vue     # Vue 3+
pnpm add @sisyphos-ui/angular # Angular 17+
```

## Import

```tsx
import "@sisyphos-ui/react/styles.css";
import { Spinner } from "@sisyphos-ui/react";
```

## Framework usage

### React 18+

```tsx
import { Spinner } from "@sisyphos-ui/react";

export const Loading = () => <Spinner size="md" color="primary" />;
```

### Vue 3+

```vue
<script setup lang="ts">
import { Spinner } from "@sisyphos-ui/vue";
</script>

<template>
  <Spinner size="md" color="primary" />
</template>
```

### Angular 17+

```ts
import { Component } from "@angular/core";
import { Spinner } from "@sisyphos-ui/angular";

@Component({
  selector: "app-loading",
  standalone: true,
  imports: [Spinner],
  template: `<sui-spinner size="md" color="primary" />`,
})
export class LoadingComponent {}
```

## Examples

### Colors

```tsx
import { Spinner } from "@sisyphos-ui/react";

export function Example() {
  return (
    <div className="flex items-center gap-6">
      <Spinner />
      <Spinner color="success" />
      <Spinner color="error" />
      <Spinner color="warning" />
      <Spinner color="info" />
    </div>
  );
}
```

### Sizes

```tsx
import { Spinner } from "@sisyphos-ui/react";

export function Example() {
  return (
    <div className="flex items-center gap-6">
      <Spinner size="xs" />
      <Spinner size="sm" />
      <Spinner size="md" />
      <Spinner size="lg" />
      <Spinner size="xl" />
    </div>
  );
}
```

### Variants & thickness

Pick between `ring`/`double` styles, tune stroke weight with `thickness`, and pass a `label` for screen readers.

```tsx
import { Spinner } from "@sisyphos-ui/react";

export function Example() {
  return (
    <>
      <Spinner variant="ring" />
      <Spinner variant="double" />
      <Spinner thickness={5} />
      <Spinner label="Saving changes…" />
    </>
  );
}
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| size | `"xs" \| "sm" \| "md" \| "lg" \| "xl"` | `"md"` | Spinner dimensions. |
| color | `"primary" \| "success" \| "error" \| "warning" \| "info" \| "neutral" \| "inherit"` | `"primary"` | Stroke color; `inherit` uses `currentColor` (useful inside buttons). |
| thickness | `number` | `3` | Ring thickness in px. |
| variant | `"ring" \| "double"` | `"ring"` | Single rotating arc, or outer arc plus counter-rotating inner arc. |
| label | `string` | `"Loading"` | Accessible label announced to screen readers. |

## Accessibility notes

- The root exposes `role="status"`, an implicit polite live region, so assistive tech is notified when the spinner appears.
- A screen-reader label is always present via `aria-label` (`label` prop, defaults to `"Loading"`).
- The SVG artwork is `aria-hidden="true"` and `focusable="false"` — only the label is announced, and the spinner never receives focus.

<!-- exports: { "Spinner": "@sisyphos-ui/react" } -->