Spinner
Indeterminate loading status for saving, refreshing and bounded asynchronous work.
Purpose
Use Spinner for an indeterminate operation whose completion percentage is unknown, such as saving, refreshing or loading a bounded panel.
Indeterminate loading
Installation
With the Siteplane registry alias configured, add the component and import the installed source from your app.
CLI
pnpm dlx shadcn@4.16.1 add @siteplane/spinnerImport
import { Spinner } from "@/components/ui/spinner";
import { Button } from "@/components/ui/button";Need the machine-readable source metadata? View registry JSON.
Usage
Spinner indicates an indeterminate wait. Prefer Button loading states for button-specific actions.
import { Spinner } from "@/components/ui/spinner";
export function Example() {
return <Spinner aria-label="Loading" />;
}Examples
Variants, sizing via className, color inheritance and loading compositions all build on the same primitive.
Variants
The default stays the animated Loader2 icon; variant switches to ring, dots, bars, spokes, pulse or comet.
Sizes
Size comes from className — there is no size prop.
Muted color
Spinner inherits currentColor, so text color utilities recolor it.
With label
When visible text carries the status, hide the spinner from assistive tech.
In button
Button has its own loading prop; a manual leading Spinner is the alternative.
Card loading
Overlay
A translucent backdrop keeps existing content visible while new data loads.
API Reference
The reference lists the source-owned exports and props that are easy to miss in visual examples. Inherited Base UI props remain available unless the wrapper narrows them.
Spinneraccepts standard element props andvariant="default" | "ring" | "dots" | "bars" | "spokes" | "pulse" | "comet".- Size and color inherit from the surrounding context unless an existing utility explicitly changes them.
- Button loading should use the Button
loadingcontract rather than manually placing a separate Spinner next to the label.
Motion
Component motion uses the shared Siteplane motion contract. See the global motion guide for provider setup, tokens and reduced-motion behavior.
- Each variant owns its loading animation; do not stack another spin, pulse or duration class on top.
- Both the provider override and the operating-system reduced-motion preference stop root and child animations through the shared
siteplane-spinner-motioncontract. The static status indicator and its semantics remain visible.
Accessibility
- A standalone Spinner uses
role="status"and needs a context-specific accessible label whenLoadingis not descriptive enough. - Keep nearby visible loading text available to assistive technology.
- Use Progress when a real percentage or stage is known.
Implementation Guidance
- Prefer the default variant unless another documented form better matches the available space.
- Do not invent a new loader animation in product code.
- Avoid showing several independent spinners for one operation.