Skip to content

Spinner

Loading indicator component with multiple sizes. Renders a CSS-animated spinner with role="status" for accessibility.

Also known as: loading indicator, loader, activity indicator, busy indicator

View in Storybook

When to use

  • Indicating loading or processing state. For percentage-based progress, use Progress.
  • For Button loading states, use Button's loading prop.

Import

tsx
import { Spinner } from '@vacano/ui'

Usage

tsx
<Spinner />

Sizes

tsx
<Spinner size="xs" />  {/* Extra small */}
<Spinner size="sm" />  {/* Small */}
<Spinner size="md" />  {/* Medium (default) */}
<Spinner size="lg" />  {/* Large */}

Accessibility

Add a label for screen readers:

tsx
<Spinner aria-label="Loading content" />

In Context

tsx
function LoadingButton() {
  const [loading, setLoading] = useState(false)

  return (
    <Button onClick={() => setLoading(true)} disabled={loading}>
      {loading ? <Spinner size="xs" /> : 'Submit'}
    </Button>
  )
}

Full Page Loading

tsx
function PageLoader() {
  return (
    <div style={{
      display: 'flex',
      justifyContent: 'center',
      alignItems: 'center',
      minHeight: '100vh'
    }}>
      <Spinner size="lg" aria-label="Loading page" />
    </div>
  )
}

Props

PropTypeDefaultDescription
size'xs' | 'sm' | 'md' | 'lg''md'Spinner size
aria-labelstring'Loading'Accessibility label for screen readers
classNamestring-CSS class name for the root element
refRef<HTMLDivElement>-Ref forwarded to the root element
data-test-idstring-Test identifier attribute

The component also accepts all standard HTMLDivElement attributes (except className and children which are overridden/excluded by the component).

INFO

The Spinner component has an empty classnames type (Record<string, never>) and does not expose any sub-element class name slots.

Released under the MIT License.