EXEPERTAI LAB

Research alpha

Time Machine
EXEPERTAI LAB
GALLERY / COLLECTION
← Browse Astryx gallery
Spinner·component·@astryxdesign/core

Spinner

An animated loading indicator for processes with unknown duration, such as data fetching or form submission. Supports visible labels, multiple sizes, and a dark background variant. For content with known dimensions, use Skeleton instead.

Open in Playground @astryxdesign/core/Spinner

Showcases and examples

4 documented examples

Spinner

A large spinner indicator.

Preview loads on approachPreview loads on approach
Exact source · spinner-showcase
// Copyright (c) Meta Platforms, Inc. and affiliates.

'use client';

import {Spinner} from '@astryxdesign/core/Spinner';

export default function SpinnerShowcase() {
  return <Spinner size="lg" />;
}

Usage

An animated loading indicator for processes with unknown duration, such as data fetching or form submission. Supports visible labels, multiple sizes, and a dark background variant. For content with known dimensions, use Skeleton instead.

  • Provide a meaningful label to describe what is loading for screen reader users.
  • Use the "onMedia" shade when placed on dark or accent-colored backgrounds.
  • Use for content areas with known dimensions; use Skeleton to preserve layout instead.
  • Stack multiple spinners in the same view; use one to represent the overall loading state.

Typed props

PropType and behavior
size'sm' | 'md' | 'lg' | 'xl' · default 'md'
Spinner size: ring diameter (10px, 14px, 18px, 28px).
shade'default' | 'onMedia' | 'subtle' | 'inherit' · default 'default'
Color shade for light or dark backgrounds.
labelReactNode
Visible content below the spinner. String labels auto-set aria-label.
aria-labelstring · default 'Loading'
Accessible name for screen readers. Defaults to label (if string) or a translated "Loading" from the i18n catalog.
xstyleStyleXStyles
StyleX styles for layout customization (margins, positioning, sizing). Must be a stylex.create() value, not an inline style object like style={{}}.

Theming

Targets

astryx-spinner

Visual props: size, shade

Variables

--spinner-diameter

Diameter of the drawn ring. Set it on a size-variant target to retheme what each named size resolves to, e.g. spinner: { 'size:xl': { '--spinner-diameter': '2.5rem' } }. The rendered box is this plus the stroke width on each side, and follows automatically. Any length works: rem, em and calc() are resolved before the ring is drawn.

Default: 10px (sm), 14px (md), 18px (lg), 28px (xl)

--spinner-stroke-width

Stroke width of both circles the ring is drawn from: the moving arc and the track behind it. Set it per size alongside the diameter. One stroke width drives both, so 0 is honoured as a zero-width stroke and paints nothing at all rather than falling back to the default; for an arc with no track behind it, set --spinner-track-color to transparent instead.

Default: 2px (sm), 3px (md), 3px (lg), 4px (xl)

--spinner-color

Color of the moving arc. Defaults to the shade's token, so set it on a shade-variant target to retheme one shade (spinner: { 'shade:subtle': { '--spinner-color': 'var(--color-text-tertiary)' } }), or on the base target to retheme all four. Accepts any color notation, including var(), color-mix() and currentColor.

Default: var(--color-accent) (default), var(--color-text-secondary) (subtle), var(--color-on-dark) (onMedia), currentColor (inherit)

--spinner-track-color

Color of the track the arc travels on. Set it to transparent for an arc with no track. The onMedia and inherit shades draw the track at reduced alpha (30%) so it reads against an arbitrary backdrop; that fade applies to a themed color too.

Default: var(--color-track) (default, subtle), var(--color-on-dark) (onMedia), currentColor (inherit)

--spinner-arc-fraction

Fraction of the ring the moving arc covers, as a plain number (not a percentage or angle). Set it on a size-variant target the same way as --spinner-diameter, e.g. spinner: { 'size:xl': { '--spinner-arc-fraction': '0.75' } } for a 270deg sweep. Only takes effect once the stylesheet loads; a render with no CSS (SSR, no-JS) always draws the default 135deg arc.

Default: 0.375 (135deg), same for every size