Skip to content

Display

Loader

Beta

An indeterminate circular loading spinner — a track ring with a rotating arc — available on web (React) and native (React Native). Five sizes (xs–xl) and a surface-aware inverse variant.

Sizes

Extra small

16px diameter. Dense inline UI, inside a small Button or IconButton.

<Loader size="xs" />

Small

24px diameter.

<Loader size="sm" />

Medium

32px diameter. The default size.

<Loader size="md" />

Large

48px diameter.

<Loader size="lg" />

Extra large

64px diameter. Full-page or full-panel loading states.

<Loader size="xl" />

Inverse

Inside an inverse <Surface> this happens automatically — Surface is the source of truth. Pass inverse explicitly only for a dark or branded background that isn’t a Surface.

Inside an inverse Surface

Surface is the source of truth: inside an inverse Surface the loader adopts inverse ink automatically — no inverse prop needed. (The rendered preview below passes inverse explicitly as a docs-site-only workaround — this ComponentPreview's client:load island doesn't carry Surface's tone context to nested framework components, so the automatic adoption shown in the code sample can't run here. Storybook and real consumer apps pick it up from Surface automatically.)

<Surface tone="inverse" className="rounded-lg p-6">
<Loader size="lg" />
</Surface>

When to use

Use Loader for an indeterminate wait — you don’t know how long an operation will take or how far through it is. It’s the default busy indicator inline in content, inside a busy control, or as a full-panel placeholder while data is fetched.

Button and IconButton render a Loader internally for their loading state; you don’t need to compose it manually there.

When not to use

  • Determinate/measurable progress: if you know the percentage complete, use a progress bar, not Loader — it has no percentage mode.
  • Content placeholders: while a piece of layout is about to appear (a card, a list row, an avatar), use a skeleton, not a spinner.

Props

Prop Type Default Description
size 'xs' | 'sm' | 'md' | 'lg' | 'xl' 'md' Diameter preset: 16 / 24 / 32 / 48 / 64px.
inverse boolean - Force the inverse (light) ink. Defaults to adopting the surrounding Surface tone.
label string 'Loading' Accessible name, announced via role="status".
id string - Web — passed to the root span.
data-testid string - Web — passed to the root span for test targeting.
nativeID string - Native — passed to the root View.
testID string - Native — passed to the root View for test targeting.
accessibilityHint string - Native — passed to the root View.

Import

Web

import { Loader } from '@checkatrade/components-web';

Native

import { Loader } from '@checkatrade/components-native';

Basic usage

<Loader />
<Loader size="lg" />
<Loader inverse /> // or automatic inside <Surface tone="inverse">
<Loader label="Loading results" />

Platform status

Platform / AreaStatus
Design (Figma) Beta
Web (React) Beta
Native (React Native) Beta
iOS (Swift) Planned
Android (Kotlin) Planned
Accessibility audit Planned

Accessibility

  • The root element carries role="status" on web (accessibilityRole="progressbar" on native) with an accessible name from label, so assistive tech announces the busy state without reading the decorative spinner graphic, which is hidden from the accessibility tree.
  • Colour is tone-aware: it resolves from the surrounding Surface tone (or the explicit inverse prop) rather than a fixed value.
  • The spinner keeps animating under prefers-reduced-motion — it’s essential busy feedback, not decorative motion.

No releases yet.