> ## Documentation Index
> Fetch the complete documentation index at: https://anvil.servicetitan.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Spinner – Design

> Spinners are ephemeral indicators for loading or processing states.

export const DoDont = ({text, type, children}) => {
  return <>
      {type === "do" && <div className="do-dont do">
          {children && <div className="do-dont-content">{children}</div>}
          <Check>
            <p>
              <strong>Do</strong>
              {text && <span className="m-inline-start-1">{text}</span>}
            </p>
          </Check>
        </div>}
      {type === "dont" && <div className="do-dont dont">
          {children && <div className="do-dont-content">{children}</div>}
          <Danger>
            <p>
              <strong>Don't</strong>
              {text && <span className="m-inline-start-1">{text}</span>}
            </p>
          </Danger>
        </div>}
      {type === "caution" && <div className="do-dont caution">
          {children && <div className="do-dont-content">{children}</div>}
          <Warning>
            <p>
              <strong>Caution</strong>
              {text && <span className="m-inline-start-1">{text}</span>}
            </p>
          </Warning>
        </div>}
    </>;
};

export const CodePreviewPlaceholder = ({double, fullWidth}) => {
  const single = <div style={{
    width: fullWidth ? "100%" : "50%",
    borderRadius: "1rem",
    display: "flex",
    padding: "1rem",
    flexDirection: "column",
    gap: "0.5rem",
    height: "10rem",
    marginBlockEnd: "1rem"
  }} className="border-width-default border-color-subdued">
      <div className="bg-strong border-radius-large" style={{
    width: "100%",
    flexGrow: "1"
  }} />
      <div className="bg-strong border-radius-large" style={{
    width: "100%",
    flexGrow: "1"
  }} />
    </div>;
  return double ? <div style={{
    display: "flex",
    gap: "1rem"
  }}>
      {single}
      {single}
    </div> : single;
};

<Frame>
  <div className="w-full h-full bg-[#FFFFFF] p-2 rounded flex items-center justify-center">
    <img noZoom src="https://mintcdn.com/servicetitan/7FmjpmD-IAznMJjW/images/docs/web/components/shared/spinner-main-image.png?fit=max&auto=format&n=7FmjpmD-IAznMJjW&q=85&s=5362cd6b921a01e83f4f31116b8d806f" width="840" height="540" data-path="images/docs/web/components/shared/spinner-main-image.png" />
  </div>
</Frame>

## Anatomy

The Spinner consists of two primary elements that work together to indicate loading or processing states.

<Frame>
  <div className="w-full h-full bg-[#FFFFFF] p-2 rounded flex items-center justify-center">
    <img
      src="https://mintcdn.com/servicetitan/usDdQzJfkl6jYYLR/images/docs/web/components/spinner/design/spinner-anatomy.png?fit=max&auto=format&n=usDdQzJfkl6jYYLR&q=85&s=9a3a1ac6c3362e5cc8ed57b95a93f890"
      alt="Spinner
Anatomy"
      width="972"
      height="540"
      data-path="images/docs/web/components/spinner/design/spinner-anatomy.png"
    />
  </div>
</Frame>

1. Track (circular background)
2. Arc (animated rotating segment)

## Options

The Spinner supports multiple sizes and color configurations to accommodate various loading indicator scenarios.

#### Size

<Frame>
  <div className="w-full h-full bg-[#FFFFFF] p-2 rounded flex items-center justify-center">
    <img
      src="https://mintcdn.com/servicetitan/usDdQzJfkl6jYYLR/images/docs/web/components/spinner/design/spinner-sizes.png?fit=max&auto=format&n=usDdQzJfkl6jYYLR&q=85&s=fba0d8409d5081a08d8266b4e0a595c9"
      alt="Spinner
Anatomy"
      width="1485"
      height="540"
      data-path="images/docs/web/components/spinner/design/spinner-sizes.png"
    />
  </div>
</Frame>

Spinners come in three sizes:

* **Small (16px)**: for inline use with text or inside buttons
* **Medium (40px)**: default size for standalone loading indicators
* **Large (80px)**: for prominent loading states

Custom sizes are also available for scenarios not covered by these existing sizes.

Spinner's track and arc scale with the size of the Spinner.

#### Color

By default, the Spinner uses the primary background color. When inherit is enabled, it inherits the current text color.

## Behavior

The Spinner responds to different size and color requirements while maintaining consistent animation.

#### Animation

The Spinner uses a continuous rotation animation at 1 second per revolution. The arc rotates clockwise around the circular track.

#### Responsive sizing

The Spinner can be resized using the `style` property. The stroke width automatically adjusts proportionally to maintain visual consistency at any size.

## Usage Guidelines

Use the Spinner when a large area of content is loading or an operation is in progress and the duration is indeterminate.

#### Common use cases

* Fetching data from an API
* Submitting a form
* Processing user actions

### When not to use

* For operations with a known duration
* For loading initial content

### Alternatives

#### Spinner vs Skeleton

Use a Spinner for focused loading states (e.g., a form submitting, fetching data from an API). Use a [Skeleton](/docs/web/components/skeleton/design) when loading initial content.

#### Spinner vs Progress Bar

Use a Spinner when the duration of the operation is unknown or indeterminate. Use a [Progress Bar](/docs/web/components/progress-bar/design) when you can track and display the actual progress percentage.

### How to Use

#### Choose the right size

Select a Spinner size appropriate for its context:

* **Small**: Inline with text or inside buttons
* **Medium**: Standalone loading indicators (default)
* **Large**: Full-page or section loading states

<Columns cols={2}>
  <DoDont type="do" text="Match the Spinner size to its surrounding context.">
    <img src="https://mintcdn.com/servicetitan/usDdQzJfkl6jYYLR/images/docs/web/components/spinner/design/spinner-in-situ-do.png?fit=max&auto=format&n=usDdQzJfkl6jYYLR&q=85&s=00c632284a5ecf423a82ef738bd8181f" alt="Loading button with a spinner matched to the text size" width="750" height="420" data-path="images/docs/web/components/spinner/design/spinner-in-situ-do.png" />
  </DoDont>

  <DoDont type="dont" text="Mismatch the Spinner size to its surrounding context.">
    <img src="https://mintcdn.com/servicetitan/usDdQzJfkl6jYYLR/images/docs/web/components/spinner/design/spinner-in-situ-dont.png?fit=max&auto=format&n=usDdQzJfkl6jYYLR&q=85&s=1d7f43d80ac70863dea48ad98337bb2f" alt="Loading button with a spinner mismatched to the text size" width="750" height="420" data-path="images/docs/web/components/spinner/design/spinner-in-situ-dont.png" />
  </DoDont>
</Columns>

#### Number of spinners

Use one Spinner at a time. Avoid showing multiple Spinners simultaneously.

<Columns cols={2}>
  <DoDont type="do" text="Use one Spinner at a time.">
    <img src="https://mintcdn.com/servicetitan/usDdQzJfkl6jYYLR/images/docs/web/components/spinner/design/spinner-one-at-a-time.png?fit=max&auto=format&n=usDdQzJfkl6jYYLR&q=85&s=dd0d3a4d02312221645890bef5da2bac" alt="Form with one loading button" width="1650" height="2058" data-path="images/docs/web/components/spinner/design/spinner-one-at-a-time.png" />
  </DoDont>

  <DoDont type="dont" text="Avoid showing multiple Spinners simultaneously.">
    <img src="https://mintcdn.com/servicetitan/usDdQzJfkl6jYYLR/images/docs/web/components/spinner/design/spinner-multiple.png?fit=max&auto=format&n=usDdQzJfkl6jYYLR&q=85&s=f3ed69ed7b6ff7a321f6e7233ec079c9" alt="Form with a loading button and multiple other spinners in the form" width="1650" height="2058" data-path="images/docs/web/components/spinner/design/spinner-multiple.png" />
  </DoDont>
</Columns>

## Keyboard Interaction

The Spinner is not focusable and does not support keyboard interaction.

### Accessibility

| Feature | Implementation                                  |
| ------- | ----------------------------------------------- |
| Role    | `role="status"` for screen reader announcements |
| ARIA    | SVG is marked with `aria-hidden="true"`         |
| Focus   | Not focusable (decorative indicator)            |

The Spinner includes `role="status"` which allows screen readers to announce when loading states change. For longer loading operations, consider providing additional context through accompanying text.

For more guidance on loading states and status updates, see [changing content best practices](/docs/accessibility/changing-content).
