React Components

# Spinner

_A visual indicator that a process is happening in the background but the interface is not yet ready for interaction._

## Overview

---

A visual indicator that a process is happening in the background but the interface is not yet ready for interaction.

<table class="_table_e3iru_2 _table--md_e3iru_59 _table--striped_e3iru_167 _identity-card__table_75e8e_7" data-ods="table" data-storybook="table"><tbody><tr><th scope="row">Name</th><td>Spinner</td></tr><tr><th scope="row">Also known as</th><td>Loading, Spin, Circular Progress</td></tr><tr><th scope="row">Links</th><td><a class="_link_1qra4_2 _identity-card__app-link_75e8e_12" data-ods="link" href="https://www.figma.com/design/9jDDTcR4a9jPRFcdjawAlf/ODS---UI-Kit?node-id=52-10340" target="_blank">Design <span class="_icon_g76et_2 _icon--external-link_g76et_256" data-ods="icon" role="presentation"></span></a><a class="_link_1qra4_2 _identity-card__app-link_75e8e_12" data-ods="link" href="https://github.com/ovh/design-system/tree/master/packages/ods-react/src/components/spinner" target="_blank">Github <span class="_icon_g76et_2 _icon--external-link_g76et_256" data-ods="icon" role="presentation"></span></a><a class="_link_1qra4_2 _identity-card__app-link_75e8e_12" data-ods="link" href="https://ovh.github.io/design-system/v18.6.4/?path=/docs/ods-components-spinner--documentation" target="_blank">Previous major version<span class="_icon_g76et_2 _icon--external-link_g76et_256" data-ods="icon" role="presentation"></span></a></td></tr></tbody></table>

## Usage

---

**Spinner** component is used as a fallback when complex content is loading in the background.

### Spinner vs Skeleton

Both **Spinner** and  indicate that content is loading, but they serve different purposes:

-   Use a **Spinner** when the content or result is unknown and the user must wait. For example, after clicking a button or loading data from an API
    
-   Use a Skeleton when the structure of the content is known, but the actual data hasn't loaded yet. It helps set expectations and makes the wait feel shorter
    

### Dos & Don'ts

| ✅ Do |
| --- |
| - Use a Spinner to indicate indeterminate loading when the duration is unknown or cannot be measured |
| - Use a Spinner when complex or background processes are happening (e.g. fetching filtered data, saving a form) |
| - Display a Spinner if the loading is expected to take more than a couple of seconds, to reassure the user |
| - Combine the Spinner with contextual messaging (e.g. "Loading [...]" or "Saving your changes") to clarify what's happening |

| ❌ Don't |
| --- |
| - Don't use multiple Spinners on the same page, it creates confusion and visual noise. Use a single centralized Spinner or loading overlay |
| - Don't use a Spinner for text or layout placeholders, use the Skeleton component instead, which better preserves structure |
| - Don't use a Spinner if the loading duration is extremely short, this can feel like a flicker or visual glitch |
| - Don't place Spinners in interactive elements like buttons without also disabling them and explaining the ongoing action |

## Placement

---

**Spinner** can be placed where needed, whether it's centered on an overlay or specific container/content in the page.

**Spinner** can widen to match its container.

## Behavior

---

The **Spinner** component has a spinning animation to show to the user that the background process is moving on.

## Variation

---

### Color

-   **Primary** (default): used in contexts where the **Spinner** is tied to the main brand action
-   **Neutral**: used for secondary or subtle loading indicators, and commonly displayed in disabled parent components to indicate background activity without drawing too much attention
-   **White**: designed for use on dark or colored backgrounds to ensure proper contrast and visibility

## Navigation

---

The **Spinner** component is non-interactive and does not receive keyboard focus. It is purely visual and serves as a loading indicator, without affecting keyboard navigation.

## Accessibility

---

The **Spinner** component does not automatically provide enough context for assistive technologies. To ensure accessibility, additional attributes must be applied to the container that holds the loading content.

### Indicating loading state

The **Spinner** itself does not convey the loading state. This responsibility falls on the container where content is being loaded by using [aria-busy](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-busy) and [aria-live](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-live) .

```jsx
<div
  aria-busy="true"
  aria-live="polite"
>
  <Spinner />
</div>
```

Explanations:

-   `aria-busy="true"` informs assistive technologies that content is being updated.
-   `aria-live="polite"` ensures that the loading message is announced when necessary without interrupting.

This approach ensures that users with assistive technologies understand when loading starts and ends.

Once the content is loaded, aria-busy should be set to false.

### Linking the Spinner to a loading description

If the **Spinner** is associated with a specific loading action, it should be explicitly labeled using [aria-labelledby](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-labelledby) or [aria-label](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-label) .

```jsx
<Spinner aria-label="Loading user profile" />
```

Screen readers will announce the label, the spinner and its current state.

Loading user profile

```jsx
<div>
  <span id="loading-text">
    Loading user profile  </span>
  <Spinner aria-labelledby="loading-text" />
</div>
```

Screen readers will announce the label, the spinner and its current state.