Patch UI

Spinner

A loading indicator with 5 visual variants. Uses currentColor so it adapts to any text color. Pure CSS animations - no JavaScript animation loops.

$npx shadcn add @patchui/spinner

Variants

Loadingring
Loadingspinner
Loadingdots
Loadingbars
Loadingring-fill

Sizes

Loadingxs
Loadingsm
Loadingmd
Loadinglg
Loadingxl

iOS-style at all sizes

Loadingxs
Loadingsm
Loadingmd
Loadinglg
Loadingxl

Color Inheritance

LoadingDefault
LoadingMuted
LoadingError
LoadingSuccess

Usage

import { Spinner } from "@patchui/react";
 
// Default ring spinner
<Spinner />
 
// iOS-style segmented bars
<Spinner variant="spinner" />
 
// Three pulsing dots
<Spinner variant="dots" />
 
// Vertical equalizer bars
<Spinner variant="bars" />
 
// Stroke-drawing ring
<Spinner variant="ring-fill" />
 
// Sizes
<Spinner size="xs" />
<Spinner size="sm" />
<Spinner size="md" />
<Spinner size="lg" />
<Spinner size="xl" />
 
// Inherits text color
<div className="text-red-500">
  <Spinner />
</div>

Props

PropTypeDefaultDescription
variant"ring" | "spinner" | "dots" | "bars" | "ring-fill""ring"The visual style of the spinner.
size"xs" | "sm" | "md" | "lg" | "xl""md"The size of the spinner.
classNamestring-Additional CSS classes.

Variants

VariantDescription
ringRotating arc - single SVG circle with a gap. Lightest weight, universal default.
spinneriOS-style 8 bars fading in sequence. Premium feel, works at all sizes.
dotsThree dots pulsing in sequence. Good for inline/chat typing indicators.
barsThree vertical bars scaling in height. Visually distinct equalizer pattern.
ring-fillSVG stroke that "draws" around a circle. Material Design feel.

Notes

  • Color inheritance: All variants use currentColor, so they adapt to the parent's text color automatically. Wrap in a colored container to change the spinner color.
  • Button loading: Use <Spinner size="sm" /> inside a Button's loading state. The ring and spinner variants work best at small sizes.
  • No JS animation: All animations are pure CSS (transform + opacity on the compositor thread). No requestAnimationFrame or JavaScript timers.
  • Accessibility: Renders with role="status" and aria-label="Loading" for screen readers.