PRIZM 4.0DSTA
All components

Spinner

Indeterminate loading indicator.

stable

Preview

LoadingLoadingLoadingLoading

Code

tsx
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

PropTypeDefaultDescription
size"sm" | "md" | "lg" | "xl""md"Spinner size: 12px / 16px / 24px / 40px.
labelstring"Loading"Accessible label exposed via role="status" + hidden <title>.
classNamestringAdditional 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.

tsx
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.

java
import design.prizm.fx.controls.PrizmSpinner;

PrizmSpinner()
PrizmSpinner(Size size)
PropTypeDefaultDescription
Sizeenum { SM, MD, LG, XL }MDDiameter in px (12 / 16 / 24 / 40), mirroring the web sizes.
setSize(Size) → voidSet 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.