# Spinner

**📖 Live documentation:** https://cds.coinbase.com/components/feedback/Spinner/?platform=mobile

A loading indicator that displays a rotating animation to communicate that content is loading or a background process is in progress.

## Import

```tsx
import { Spinner } from '@coinbase/cds-mobile/loaders/Spinner'
```

## Examples

On mobile, Spinner wraps React Native's `ActivityIndicator` component.

### Basics

By default, the spinner renders at the `small` size with the theme's primary background color.

```jsx
<Spinner />
```

### Buttons

Use the `loading` prop on [Button](/components/inputs/Button) and [IconButton](/components/inputs/IconButton) to show a spinner during async operations. The button becomes non-interactive while preserving its dimensions.

```jsx
<HStack gap={2} alignItems="center">
  <Button onPress={handlePress} loading={isLoading}>
    Submit
  </Button>
  <Button onPress={handlePress} loading={isLoading} variant="secondary">
    Save
  </Button>
  <IconButton
    onPress={handlePress}
    loading={isLoading}
    name="refresh"
    accessibilityLabel="Refresh"
  />
</HStack>
```

### Styling

#### Sizing

Use the `size` prop to control the spinner dimensions. Available values are `small` (default) and `large`.

```jsx
<HStack gap={3} alignItems="center">
  <Spinner size="small" />
  <Spinner size="large" />
</HStack>
```

#### Animating

Use the `animating` prop to control whether the spinner is spinning. Set to `false` to show a static indicator, which can be useful for loading state transitions.

```jsx
<HStack gap={3} alignItems="center">
  <Spinner animating={true} />
  <Spinner animating={false} />
</HStack>
```

### Accessibility

The underlying `ActivityIndicator` provides built-in accessibility support. Use `accessibilityLabel` to provide additional context for screen readers.

```jsx
<Spinner size="large" accessibilityLabel="Loading your transactions" />
```

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `animating` | `boolean` | No | `-` | Whether to show the indicator (true, the default) or hide it (false). |
| `color` | `string \| OpaqueColorValue` | No | `-` | The foreground color of the spinner (default is gray). |
| `hidesWhenStopped` | `boolean` | No | `-` | Whether the indicator should hide when not animating (true by default). |
| `onPointerCancel` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerCancelCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerDown` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerDownCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerEnter` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerEnterCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerLeave` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerLeaveCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerMove` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerMoveCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerUp` | `((event: PointerEvent) => void)` | No | `-` | - |
| `onPointerUpCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
| `size` | `number \| small \| large` | No | `-` | Size of the indicator. Small has a height of 20, large has a height of 36.  enum(small, large) |
| `style` | `null \| false \|  \| ViewStyle \| RegisteredStyle<ViewStyle> \| RecursiveArray<Falsy \| ViewStyle \| RegisteredStyle<ViewStyle>>` | No | `-` | - |
| `testID` | `string` | No | `-` | Used to locate this view in end-to-end tests. Used to locate this element in unit and end-to-end tests. Under the hood, testID translates to data-testid on Web. On Mobile, testID stays the same - testID |


