Spinner

Status-role loading indicator in three sizes.

atomsSource
import { Spinner } from '@elirobinson/react/components/atoms/Spinner';

Styles: @elirobinson/react/styles/atoms/Spinner.css — already included when you import @elirobinson/react/styles.css.

Show code
import { Spinner } from '@elirobinson/react/components/atoms/Spinner';

export default function Basic() {
  return <Spinner />;
}

When to use it

Use Spinner for a small, indeterminate "working" indicator — you don't know how long it'll take. Use Progress instead the moment you actually know the percent complete.

Sizes

Show code
import { Spinner } from '@elirobinson/react/components/atoms/Spinner';

export default function Sizes() {
  return (
    <div className="demo-row">
      <Spinner size="sm" />
      <Spinner size="md" />
      <Spinner size="lg" />
    </div>
  );
}

Inside a button

A common pattern: a disabled button showing its own loading state.

Show code
import { Button } from '@elirobinson/react/components/atoms/Button';
import { Spinner } from '@elirobinson/react/components/atoms/Spinner';

export default function InButton() {
  return (
    <Button disabled>
      <Spinner size="sm" aria-hidden="true" />
      Saving changes
    </Button>
  );
}

Props

PropTypeDefaultDescription
labelstringLoading
size"sm" | "md" | "lg"md

Also accepts all Omit<HTMLAttributes<HTMLSpanElement>, 'role'> props.

Accessibility

  • Renders role="status" with aria-label={label} (default "Loading") — a live region announced once when it mounts. role is fixed: the type omits it from the props you can pass, so you can't accidentally break the live region.
  • When adjacent visible text already says the same thing — a "Saving changes" button, for example — pass aria-hidden="true" on the Spinner so the two don't both get announced, as in the button demo above.
  • Give it a specific label when the default "Loading" isn't precise enough ("Loading invoices") and no visible text nearby already says so.

Do

  • Give Spinner a specific label when the default "Loading" isn’t precise enough.
  • Use size="sm" inline next to text and reserve lg for a full-section loading state.
  • Pass aria-hidden="true" when adjacent visible text already announces the same loading state.

Don't

  • Pair a Spinner with visible "Loading…" text without hiding one of the two from assistive tech — that’s a double announcement.
  • Use Spinner for a task where you actually know the percent complete — that’s what Progress is for.
  • Try to override role — the type doesn’t allow it; status is the fixed contract.