Skip to content

Spinner

A circular loading indicator for asynchronous operations. Available in three sizes and multiple colour variants.

Preview

Variants

Brand
Neutral
On dark

In a button

Sizes

SizeDimensionsBorder width
sm16 × 16 px2 px
md24 × 24 px2 px
lg40 × 40 px3 px

Variants

  • Brand (default) -- uses --vp-c-brand-1. Use on neutral backgrounds.
  • Neutral -- grey. Use for subtle loading states.
  • On dark -- white. Use on dark or coloured backgrounds.
  • On light -- dark. Use on white backgrounds in dark mode contexts.

Props

PropTypeDefaultDescription
size'sm' | 'md' | 'lg''md'Spinner dimensions
variant'brand' | 'neutral' | 'on-dark' | 'on-light''brand'Colour variant
labelstring'Loading'Accessible label

Code example

React

tsx
import { Spinner } from '@thepace/lexicon/components';

<Spinner size="lg" />
<Spinner size="sm" variant="neutral" />

Vanilla HTML

html
<span class="lex-spinner lex-spinner--md" role="status"
      aria-label="Loading"></span>
<span class="lex-spinner lex-spinner--lg lex-spinner--neutral"
      role="status" aria-label="Loading"></span>

CSS class reference

ClassPurpose
.lex-spinnerBase spinner (animated border)
.lex-spinner--sm16 px
.lex-spinner--md24 px
.lex-spinner--lg40 px
.lex-spinner--neutralGrey colour
.lex-spinner--on-darkWhite colour
.lex-spinner--on-lightDark colour

Accessibility

  • Always add role="status" and aria-label="Loading" (or a context-specific label).
  • When used inside a button, set aria-busy="true" on the button.
  • Ensure the spinner is visible against its background in both themes.

Guidelines

Do

  • Use the smallest size that communicates loading clearly.
  • Pair with descriptive text for longer operations (e.g. "Loading results...").

Don't

  • Don't use a spinner for operations under 300 ms — the flash is distracting.
  • Don't use multiple spinners in the same view — consolidate into one loading state.

Released under the MIT License. A product by the pace.