State & Feedback Systems

Spinner Set

Four React loading indicators — ring, dots, bars and a tracing brand mark — with adjustable size, speed and label, falling back to a static icon with text under reduced motion.

One component covering four common loading indicators: a ring spinning at constant speed, three dots rising in sequence, bars pulsing up and down, and a mark that traces back and forth along the brand curve. Graphics inherit the text colour by default, so they fit straight into a button, a table row or a full-page loading area; the label is screen-reader only by default, or can be shown next to the graphic. When the user turns on reduced motion every loop stops, a static icon takes its place and the text is forced visible.

Bring this into your project

Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.

npx webberui@latest add spinner-set.en

New project or installation trouble? Start here →

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

0.8
Active edited usageDefault props
<SpinnerSet/>

The complete example includes the preview layout and data. Install the component first, then paste this file into your project.

Installation

npx webberui@latest add https://webberui.com/r/spinner-set.en.json

Or, once registries are configured in components.json, install it as @webberui/spinner-set.

Usage

import { SpinnerSet } from "@/components/ui/spinner-set";

<SpinnerSet />
<SpinnerSet variant="dots" size="lg" showLabel label="Syncing" />
<SpinnerSet variant="brand" size={32} speed={2} />

<button type="button" aria-busy={saving} disabled={saving}>
  {saving ? <SpinnerSet size="xs" label="Saving" /> : null}
  Save
</button>

Props

PropTypeDefaultDescription
variant"ring" | "dots" | "bars" | "brand""ring"Indicator style: ring, dots, bars or a tracing brand mark
size"xs" | "sm" | "md" | "lg" | number"md"Edge length: xs 12px, sm 16px, md 20px, lg 28px, or a pixel number
labelstring"Loading"Loading text; screen-reader only by default (the Chinese build defaults to "載入中", "Loading")
showLabelbooleanfalseShow the label text next to the graphic
speednumberper variantSeconds per loop; ring 0.8, dots 1.2, bars 1.0, brand 1.6 — once set, it applies to every variant
colorstringcurrentColorGraphic colour; when omitted reads --wb-spinner-set-color, then falls back to currentColor
brandPathstringWebberUI brand curveSVG path traced by the brand variant (64×64 coordinates)
classNamestring—Passed through to the outermost container

The types SpinnerSetVariant and SpinnerSetSize are exported as well.

How it works

  • The ring is a 25%-opacity full circle plus a 25%-length arc; arc length is expressed with pathLength=100, so nothing needs recalculating when the size changes.
  • Each dot is delayed by speed/6 and each bar by speed/8, so the rhythm keeps its proportions when you change speed.
  • The brand variant traces back and forth with pathLength 0→1→0; the stroke thickens automatically at small sizes so it stays legible at 12px.
  • The root writes --wb-spinner-set-duration (the speed in seconds), so your own CSS can keep other animations on the same beat.
  • The colour variable --wb-spinner-set-color can be set in a theme or on a parent; a color prop takes precedence.

Accessibility

  • The root is role="status" with aria-live="polite" and contains the label text, so screen readers announce the loading state
  • The graphic itself is aria-hidden and is not read out as stray images or shapes
  • When used inside a button, set aria-busy on the button and disable it to prevent double submits
  • When the user's system has "reduce motion" enabled, every loop stops: ring becomes a static Loader icon, dots and bars show three static dots and four static bars, brand shows the fully drawn mark, and the label text is forced visible