A set of 5×5 dot matrix loaders, each a self-contained SVG.

OrbitA dot circles the perimeter.RippleRings ripple outward from the center.BloomBrightness blooms outward along the diagonal.HelixBrightness winds around like a strand.
import { Bloom, Helix, Orbit, Ripple } from "@/ui/dot-matrix";

export default function LoadersDemo() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-12">
      <Orbit />
      <Ripple />
      <Bloom />
      <Helix />
    </div>
  );
}

Every loader is one inline SVG with a single embedded keyframe and a per-dot delay map, no shared stylesheet and no JavaScript runtime.

Thirty-four named patterns, each exported as its own component.

AttentionRows light top to bottom in a steady sweep.
attention
Auth HandshakeLeft and right halves flash and meet in the middle.
auth-handshake
BackpropPulses propagate forward then back across columns.
backprop
BeaconA bright pulse rotates around the grid.
beacon
BloomBrightness blooms outward along the diagonal.
bloom
Cache WarmWarmth spreads from the corners inward.
cache-warm
Cluster SyncQuadrants sync in turn around an empty cross.
cluster-sync
CompileRows resolve from the bottom up.
compile
ConstellationStars twinkle on a deterministic loop.
constellation
CronThe outer ring ticks around like a clock.
cron
DeployColumns roll out left to right.
deploy
DiffusionNoise resolves into a steady signal.
diffusion
DriftA soft wave drifts along the diagonal.
drift
EmbeddingBrightness collapses inward to the center.
embedding
Flower BloomPetals brighten and fade around the core.
flower-bloom
Gradient DescentRows descend, fading as they settle.
gradient-descent
HashCells flicker in a scattered, fixed pattern.
hash
Heart PulseA heart beats with a double thump.
heart-pulse
HelixBrightness winds around like a strand.
helix
Index BuildPairs build inward from the edges.
index-build
LatticeThe grid breathes in two phases.
lattice
OrbitA dot circles the perimeter.
orbit
Plus PulseA plus shape pulses in and out.
plus-pulse
QuantizeCells snap between levels in steps.
quantize
Rate LimitThe middle row gates through in bursts.
rate-limit
RippleRings ripple outward from the center.
ripple
SnowflakeA six-fold flake shimmers softly.
snowflake
Sound BarsColumns rise and fall like a meter.
sound-bars
Star BurstA star flares from the center.
star-burst
SyncThe four corners flash in rotation.
sync
Token StreamTokens emit column by column.
token-stream
Twin HelixTwo strands pulse out of phase.
twin-helix
Vector IndexDiagonals index across the grid.
vector-index
WebhookA pulse radiates outward on each call.
webhook
import {
  Attention,
  AuthHandshake,
  Backprop,
  Beacon,
  Bloom,
  CacheWarm,
  ClusterSync,
  Compile,
  Constellation,
  Cron,
  Deploy,
  Diffusion,
  Drift,
  Embedding,
  FlowerBloom,
  GradientDescent,
  Hash,
  HeartPulse,
  Helix,
  IndexBuild,
  Lattice,
  Orbit,
  PlusPulse,
  Quantize,
  RateLimit,
  Ripple,
  Snowflake,
  SoundBars,
  StarBurst,
  Sync,
  TokenStream,
  TwinHelix,
  VectorIndex,
  Webhook,
} from "@/ui/dot-matrix";

const LOADERS = [
  { name: "attention", Loader: Attention },
  { name: "auth-handshake", Loader: AuthHandshake },
  { name: "backprop", Loader: Backprop },
  { name: "beacon", Loader: Beacon },
  { name: "bloom", Loader: Bloom },
  { name: "cache-warm", Loader: CacheWarm },
  { name: "cluster-sync", Loader: ClusterSync },
  { name: "compile", Loader: Compile },
  { name: "constellation", Loader: Constellation },
  { name: "cron", Loader: Cron },
  { name: "deploy", Loader: Deploy },
  { name: "diffusion", Loader: Diffusion },
  { name: "drift", Loader: Drift },
  { name: "embedding", Loader: Embedding },
  { name: "flower-bloom", Loader: FlowerBloom },
  { name: "gradient-descent", Loader: GradientDescent },
  { name: "hash", Loader: Hash },
  { name: "heart-pulse", Loader: HeartPulse },
  { name: "helix", Loader: Helix },
  { name: "index-build", Loader: IndexBuild },
  { name: "lattice", Loader: Lattice },
  { name: "orbit", Loader: Orbit },
  { name: "plus-pulse", Loader: PlusPulse },
  { name: "quantize", Loader: Quantize },
  { name: "rate-limit", Loader: RateLimit },
  { name: "ripple", Loader: Ripple },
  { name: "snowflake", Loader: Snowflake },
  { name: "sound-bars", Loader: SoundBars },
  { name: "star-burst", Loader: StarBurst },
  { name: "sync", Loader: Sync },
  { name: "token-stream", Loader: TokenStream },
  { name: "twin-helix", Loader: TwinHelix },
  { name: "vector-index", Loader: VectorIndex },
  { name: "webhook", Loader: Webhook },
];

export default function LoadersGalleryDemo() {
  return (
    <div className="grid w-full grid-cols-2 gap-x-6 gap-y-10 sm:grid-cols-3 md:grid-cols-4">
      {LOADERS.map(({ name, Loader }) => (
        <div key={name} className="flex flex-col items-center gap-4">
          <div className="flex h-8 items-center justify-center">
            <Loader aria-label={name} />
          </div>
          <span className="font-mono text-xs text-neutral-500 dark:text-neutral-400">{name}</span>
        </div>
      ))}
    </div>
  );
}

Color

Pass any CSS color to color. It defaults to the current theme's foreground — black on light, white on dark.

RippleRings ripple outward from the center.RippleRings ripple outward from the center.RippleRings ripple outward from the center.
import { Ripple } from "@/ui/dot-matrix";

export default function LoadersColorDemo() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-12">
      <Ripple color="var(--color-accent-500)" />
      <Ripple color="var(--color-success-500)" />
      <Ripple color="var(--color-danger-500)" />
    </div>
  );
}

Sizing

Set size to scale a loader. Drop it down for an inline or chat-sized loader, or push it up for emphasis. Every other example here uses the default.

Cache WarmWarmth spreads from the corners inward.Cache WarmWarmth spreads from the corners inward.Cache WarmWarmth spreads from the corners inward.Cache WarmWarmth spreads from the corners inward.
import { CacheWarm } from "@/ui/dot-matrix";

export default function LoadersSizesDemo() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-12">
      <CacheWarm size={16} />
      <CacheWarm />
      <CacheWarm size={40} />
      <CacheWarm size={64} />
    </div>
  );
}

API

Every loader accepts the same props.

PropTypeDefault
sizenumber24
speednumber1
colorstringcurrentColor
classNamestring-
aria-labelstring"Loading"