Spinner

Animated loading indicator with size and color variants.

Installation
$Terminal
npx shadcn@latest add https://sdk-components.thesqd.com/r/spinner.json
Usage
Import the master file and pass `size` + `variant` (or the `color` alias). `animate-spin` is always on.
TSImport
import { Spinner, type SpinnerVariant, type SpinnerSize } from "@/components/ui/spinner";
TSExample
import { Spinner } from "@/components/ui/spinner";

export function Example() {
  return <Spinner size="md" variant="brand" />;
}
Composition
Anatomy of the Spinner primitive.
Spinner                          (single component — flat prop API)
├── size="sm | md | lg | xl"     (default "md")
├── variant="brand | current | muted | destructive | pixels-1 | pixels-2"   (default "brand")
├── color=…                       (named tint alias OR any CSS color string)
├── icon={LucideIcon}            (override the default LoaderIcon)
└── ...props                      (forwarded to the underlying svg)
Default
Plain brand spinner at the default `md` size.
Custom icon
Pass any lucide icon component via the `icon` prop to swap the default `LoaderIcon`.
Size
Four sizes — `sm`, `md`, `lg`, and `xl` — using the brand tint.
Pixels
Two WebGL pixel loaders exposed as Spinner variants: `variant="pixels-1"` (a dithered, lit sphere) and `variant="pixels-2"` (a dithered swirl). Brand-tinted by default; pass any CSS `color` (e.g. `#0ea5e9`) to retint, and `size` to scale.
Button
Drop a Spinner inside a Button using `variant="current"` so it inherits the button label color. Tag with `data-icon="inline-start"` or `"inline-end"` to get the right padding.
Badge
Same pattern inside a Badge — use `variant="current"` and `data-icon` to slot the spinner before or after the label.
SyncingWorking
Empty state
Center a muted `xl` spinner inside a placeholder Card while data is loading.
Item
Drop a Spinner inside a muted `Item` with a `message` title and a trailing `label`. Both are passed as props on the demo.
Processing payment...
$100.00
Item (Plain)
Same Item composition with `background={false}` and no `label` — a plain muted row with just the spinner and message.
Loading...
API Reference
Props exposed by the Spinner and SpinnerItem components.

Spinner

PropTypeDefaultDescription
size"sm" | "md" | "lg" | "xl""md"Icon dimensions — maps to size-3 / size-4 / size-5 / size-6.
variant"brand" | "current" | "muted" | "destructive" | "pixels-1" | "pixels-2""brand"Look. Named tints render a spinning icon (`current` inherits the parent's color); `pixels-1` (dither sphere) and `pixels-2` (dither swirl) render WebGL pixel loaders.
colorSpinnerVariant | (string & {})A named tint (alias of `variant`) OR any CSS color string (`#0ea5e9`, `rgb(...)`) to tint the whole spinner, pixel variants included.
iconLucideIconLoaderIconOverride the default lucide icon (e.g. `LoaderCircleIcon`).
classNamestringOverride or extend the resolved variant classes.

SpinnerItem

PropTypeDefaultDescription
messagestringTitle text shown next to the spinner.
labelstringOptional trailing text (e.g. `$100.00`). When undefined the trailing slot is not rendered.
backgroundbooleantrueWhen `true`, tints the row with the sidebar-hover bg (`#341756/10` light, `white/10` dark). Set to `false` for a plain muted Item with no tint.
iconLucideIconOverride the spinner's lucide icon.
spinnerSize"sm" | "md" | "lg" | "xl"Forwarded to the inner Spinner's `size` prop.
spinnerVariant"brand" | "current" | "muted" | "destructive"Forwarded to the inner Spinner's `variant` prop.