Skip to content

Spinner

SM, under 950B gzipped

A loading indicator announced once via role=status.

Category
Feedback & status
Budget
sm, single-purpose control
Runtime deps
None

Preview

Preview language
Loading

This is the exact fixture the conformance suite renders in CI. Switch the language to see the component mirror and reformat.

Install

npx shadcn@latest add https://kata-ui-rho.vercel.app/r/spinner.json

Copies the source into your project. Pulls in 2 primitives: cn, visually-hidden.

Source

import { VisuallyHidden } from "./visually-hidden";
import { cn } from "../lib/cn";

export interface SpinnerProps {
  label?: string;
  className?: string;
}

/**
 * A loading indicator. The spin itself is `aria-hidden`; the label — spoken
 * once via `role="status"`, not repeated on every animation frame — is what
 * assistive technology actually hears.
 */
export function Spinner({ label = "Loading…", className }: SpinnerProps) {
  return (
    <span role="status" className={cn("inline-flex items-center gap-2", className)}>
      <span
        aria-hidden="true"
        className="size-4 shrink-0 animate-spin rounded-full border-2 border-current border-t-transparent motion-reduce:animate-none"
      />
      <VisuallyHidden>{label}</VisuallyHidden>
    </span>
  );
}

What CI checks

Used by

← All components