Loaders

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

A dot circles the perimeter.Rings ripple outward from the center.Brightness blooms outward along the diagonal.Brightness winds around like a strand.
import { Bloom } from "@arshad/ui/components/dot-matrix/bloom";
import { Helix } from "@arshad/ui/components/dot-matrix/helix";
import { Orbit } from "@arshad/ui/components/dot-matrix/orbit";
import { Ripple } from "@arshad/ui/components/dot-matrix/ripple";

export function Basic() {
  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.

Rows light top to bottom in a steady sweep.
attention
Left and right halves flash and meet in the middle.
auth-handshake
Pulses propagate forward then back across columns.
backprop
A bright pulse rotates around the grid.
beacon
Brightness blooms outward along the diagonal.
bloom
Warmth spreads from the corners inward.
cache-warm
Quadrants sync in turn around an empty cross.
cluster-sync
Rows resolve from the bottom up.
compile
Stars twinkle on a deterministic loop.
constellation
The outer ring ticks around like a clock.
cron
Columns roll out left to right.
deploy
Noise resolves into a steady signal.
diffusion
A soft wave drifts along the diagonal.
drift
Brightness collapses inward to the center.
embedding
Petals brighten and fade around the core.
flower-bloom
Rows descend, fading as they settle.
gradient-descent
Cells flicker in a scattered, fixed pattern.
hash
A heart beats with a double thump.
heart-pulse
Brightness winds around like a strand.
helix
Pairs build inward from the edges.
index-build
The grid breathes in two phases.
lattice
A dot circles the perimeter.
orbit
A plus shape pulses in and out.
plus-pulse
Cells snap between levels in steps.
quantize
The middle row gates through in bursts.
rate-limit
Rings ripple outward from the center.
ripple
A six-fold flake shimmers softly.
snowflake
Columns rise and fall like a meter.
sound-bars
A star flares from the center.
star-burst
The four corners flash in rotation.
sync
Tokens emit column by column.
token-stream
Two strands pulse out of phase.
twin-helix
Diagonals index across the grid.
vector-index
A pulse radiates outward on each call.
webhook
import { Attention } from "@arshad/ui/components/dot-matrix/attention";
import { AuthHandshake } from "@arshad/ui/components/dot-matrix/auth-handshake";
import { Backprop } from "@arshad/ui/components/dot-matrix/backprop";
import { Beacon } from "@arshad/ui/components/dot-matrix/beacon";
import { Bloom } from "@arshad/ui/components/dot-matrix/bloom";
import { CacheWarm } from "@arshad/ui/components/dot-matrix/cache-warm";
import { ClusterSync } from "@arshad/ui/components/dot-matrix/cluster-sync";
import { Compile } from "@arshad/ui/components/dot-matrix/compile";
import { Constellation } from "@arshad/ui/components/dot-matrix/constellation";
import { Cron } from "@arshad/ui/components/dot-matrix/cron";
import { Deploy } from "@arshad/ui/components/dot-matrix/deploy";
import { Diffusion } from "@arshad/ui/components/dot-matrix/diffusion";
import { Drift } from "@arshad/ui/components/dot-matrix/drift";
import { Embedding } from "@arshad/ui/components/dot-matrix/embedding";
import { FlowerBloom } from "@arshad/ui/components/dot-matrix/flower-bloom";
import { GradientDescent } from "@arshad/ui/components/dot-matrix/gradient-descent";
import { Hash } from "@arshad/ui/components/dot-matrix/hash";
import { HeartPulse } from "@arshad/ui/components/dot-matrix/heart-pulse";
import { Helix } from "@arshad/ui/components/dot-matrix/helix";
import { IndexBuild } from "@arshad/ui/components/dot-matrix/index-build";
import { Lattice } from "@arshad/ui/components/dot-matrix/lattice";
import { Orbit } from "@arshad/ui/components/dot-matrix/orbit";
import { PlusPulse } from "@arshad/ui/components/dot-matrix/plus-pulse";
import { Quantize } from "@arshad/ui/components/dot-matrix/quantize";
import { RateLimit } from "@arshad/ui/components/dot-matrix/rate-limit";
import { Ripple } from "@arshad/ui/components/dot-matrix/ripple";
import { Snowflake } from "@arshad/ui/components/dot-matrix/snowflake";
import { SoundBars } from "@arshad/ui/components/dot-matrix/sound-bars";
import { StarBurst } from "@arshad/ui/components/dot-matrix/star-burst";
import { Sync } from "@arshad/ui/components/dot-matrix/sync";
import { TokenStream } from "@arshad/ui/components/dot-matrix/token-stream";
import { TwinHelix } from "@arshad/ui/components/dot-matrix/twin-helix";
import { VectorIndex } from "@arshad/ui/components/dot-matrix/vector-index";
import { Webhook } from "@arshad/ui/components/dot-matrix/webhook";

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 function Gallery() {
  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 [contain-intrinsic-size:auto_5rem] [content-visibility:auto]"
        >
          <div className="flex h-8 items-center justify-center">
            <Loader aria-label={name} />
          </div>
          <span className="font-mono text-xs text-neutral-600 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.

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

export function Color() {
  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.

Warmth spreads from the corners inward.Warmth spreads from the corners inward.Warmth spreads from the corners inward.Warmth spreads from the corners inward.
import { CacheWarm } from "@arshad/ui/components/dot-matrix/cache-warm";

export function Sizes() {
  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
aria-labelstring"Loading"

Plus every SVG attribute, including className, style, and ref.