Spinner
Indeterminate loading indicator.
Preview
Code
import { Spinner } from "@/components/ui/spinner";
export function Example() {
return (
<div className="flex items-center gap-4">
<Spinner size="sm" />
<Spinner />
<Spinner size="lg" />
<Spinner size="xl" />
</div>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| size | "sm" | "md" | "lg" | "xl" | "md" | Spinner size: 12px / 16px / 24px / 40px. |
| label | string | "Loading" | Accessible label exposed via role="status" + hidden <title>. |
| className | string | — | Additional Tailwind classes, merged with the component's defaults via cn(). |
Animated SVG spinner. Use for indeterminate loading.
All components also accept standard HTML attributes for their root element (e.g. `id`, `aria-*`, `data-*`, event handlers) and forward `ref` where applicable.
Source
The full implementation of components/ui/spinner.tsx is below — copy it into your project and own it. Some components import the cn helper from lib/utils or other primitives; copy those too.
import { cn } from "@/lib/utils";
import { type VariantProps, cva } from "class-variance-authority";
import { type SVGAttributes, forwardRef } from "react";
const spinnerVariants = cva("animate-spin text-fg-muted", {
variants: {
size: {
sm: "h-3 w-3",
md: "h-4 w-4",
lg: "h-6 w-6",
xl: "h-10 w-10",
},
},
defaultVariants: { size: "md" },
});
export interface SpinnerProps
extends SVGAttributes<SVGElement>,
VariantProps<typeof spinnerVariants> {
label?: string;
}
export const Spinner = forwardRef<SVGSVGElement, SpinnerProps>(
({ className, size, label = "Loading", ...props }, ref) => (
<svg
ref={ref}
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
// biome-ignore lint/a11y/useSemanticElements: <svg role="status"> is the standard live-region pattern for an inline loading indicator with an aria-label.
role="status"
aria-label={label}
className={cn(spinnerVariants({ size }), className)}
{...props}
>
<title>{label}</title>
<circle cx="12" cy="12" r="10" stroke="currentColor" strokeOpacity="0.25" strokeWidth="3" />
<path
d="M22 12a10 10 0 0 1-10 10"
stroke="currentColor"
strokeWidth="3"
strokeLinecap="round"
/>
</svg>
),
);
Spinner.displayName = "Spinner";JavaFX
Ships in the PRIZM JavaFX library for thick-client C3 apps as PrizmSpinner (extends Region). Run the gallery to see it natively.
import design.prizm.fx.controls.PrizmSpinner;
PrizmSpinner()
PrizmSpinner(Size size)| Prop | Type | Default | Description |
|---|---|---|---|
| Size | enum { SM, MD, LG, XL } | MD | Diameter in px (12 / 16 / 24 / 40), mirroring the web sizes. |
| setSize | (Size) → void | — | Set the diameter from the scale. |
A custom Region — a muted track ring (25% opacity) plus a 90° arc rotated continuously, matching the web. (The stock ProgressIndicator's indeterminate state renders as spinning segments, which don't match.) Styled by the .prizm-spinner rules. Mirrors components/ui/spinner.tsx.