Spinner

Work of unknown length in a small area, such as a panel that is updating, as a turning arc.

StableSince 1.0.0
On this page

Import

import { Spinner } from '@envsemble/envui';

Usage

A Spinner's label names the work it stands for, such as Updating tasks, and names it as a progress bar for assistive technology; leave it out where a busy control or region already says what happens, and the spinner is hidden. size is sm, 1 rem, md, 1.5 rem and the default, or lg, 3 rem, as data-size.

LoadingPreview.tsx
import { useEffect, useState } from 'react';
import { Column, Spinner, Surface, Text } from '@envsemble/envui';

export default function LoadingPreview() {
  const [loaded, setLoaded] = useState(false);
  useEffect(() => {
    // Stands in for rendering the file's first page.
    const rendering = setTimeout(() => setLoaded(true), 2000);
    return () => clearTimeout(rendering);
  }, []);
  return (
    // The preview's frame keeps its size while the file renders, with the spinner in its middle,
    // and the page takes the spinner's place.
    <Surface background="muted" aria-busy={!loaded} style={{ inlineSize: 'min(100%, 20rem)' }}>
      <Column align="center" justify="center" style={{ minBlockSize: '10rem' }}>
        {loaded ? (
          <Surface
            background="page"
            radius="sm"
            padding={3}
            render={<Column gap={1} />}
            aria-label="First page of quarterly-report.pdf"
            role="img"
            // A page's proportions, a little narrower than tall.
            style={{ inlineSize: '7.5rem', blockSize: '9.5rem' }}
          >
            <Text variant="caption">Quarterly report</Text>
            <Text variant="caption" emphasis="muted">
              Northwind · March 2026
            </Text>
          </Surface>
        ) : (
          <Spinner size="lg" label="Loading the preview of quarterly-report.pdf" />
        )}
      </Column>
    </Surface>
  );
}

With its label

showLabel shows the label beside the spinner, in a busy status line that centres the two in its row, for loading with no known shape, such as results whose number and shape aren't known until they arrive. Without a label it says Loading, in the provider's language.

<Spinner label="Searching documents" showLabel />

Composition

For the work that follows a press, such as saving, set pending on the Button that started it, and for content of a known shape, skeleton, rather than a spinner. Set aria-busy on the region that updates, and put the result or the error in the spinner's place when the work ends.

The parts are the spinner, env-spinner, its arc, env-spinner-arc, and with showLabel the label beside it, env-spinner-label.

Accessibility

You provide

  • A label, unless a busy control or region already says what happens.
  • aria-busy on the region that updates, and a status where people wait for a result.
  • The result or the error in place of the spinner when the work ends.

envUI provides

  • role="progressbar" named by label, or the spinner hidden without one.
  • With showLabel, a busy role="status" whose label, Loading by default in the provider's language, is read as the status.
  • A slower turn with a fixed arc under reduced motion, instead of stopping.

Props

Spinner

Work of unknown length in a small area, such as a panel that is updating: an arc in the control blue that turns, and keeps turning slowly with a reduced-motion preference. With a label it is a progress bar named by it; without one it is hidden from assistive technology. With showLabel it is a status line with its label beside it, for loading with no known shape. The hook --env-spinner-color recolors it, such as to a button's label color.

PropTypeDescription
label
string
The work it stands for, such as Refreshing members or Loading project. Alone it names the spinner as a progress bar for assistive technology; with showLabel it shows beside it. Leave it out where a busy control or region already says so; the spinner is then hidden from assistive technology.
showLabelDefault false
boolean
Show the label beside the spinner, for loading with no known shape, such as search results: a status line, marked busy, that centers the spinner and its label in its row. Without a label it says Loading in the provider's language, from EnvUIProvider's messages.common.loading.
sizeDefault 'md'
'sm''md''lg'
sm, 1 rem, inside controls and beside a line of text; md, 1.5 rem, beside a heading or in a panel; or lg, 3 rem, in the middle of a region whose content is on its way.

Also accepts the native props of <span>, such as ref, className and aria-* attributes.

Part names

Each part's class and state attributes are public and versioned, for an application's CSS to style.

env-spinner
The spinner, data-label-hidden while its label is hidden, or else the status line that holds it and its label.
env-spinner-arc
The turning arc.
env-spinner-label
The label shown beside the spinner, which says what is loading.
data-label-hidden
Present
data-size
lg · md · sm

Changelog

1.0.0

showLabel shows the label beside the spinner, in a busy status, for loading with no known shape, in place of the LoadingState component of 1.0.0-prerelease.0. size is sm, md or lg, as data-size; the drawing is hidden from assistive technology also when the spinner has a label.

1.0.0-prerelease.6

A turn lasts six times --env-motion-duration-slow, about as long as before, with --env-motion-ease, so durations of 0s stop it.