Skip to content
v2.5.0
English
Русский
Documentation

Spinner

Spinner is the loading indicator for pending states and asynchronous actions.

Patterns

Inline Status Row

When to use:

  • one action is pending and nearby text can explain it

Composition notes:

  • pair the spinner with short status text
  • keep the size small

Trade-offs:

  • compact and clear
  • depends on nearby copy for meaning
inline-status-row.tsx · 13 lines
import { Spinner, Text } from '@vega-ui/react';
import { useId } from 'react';

export default function InlineStatusRow() {
  const labelId = useId();

  return (
    <div style={{ display: 'flex', gap: 'var(--spacing-4)', alignItems: 'center' }}>
      <Spinner size={2} aria-labelledby={labelId} />
      <Text id={labelId} size={2}>Syncing 128 contacts from Google</Text>
    </div>
  );

Centered Surface Loader

When to use:

  • a panel or section is loading and content is not yet ready

Composition notes:

  • center the spinner within a reserved area
  • choose a larger size than inline usage

Trade-offs:

  • easy to notice
  • removes content detail while loading
dialog-content-loader.tsx · 68 lines
import {
  Button,
  Dialog,
  DialogClose,
  DialogContent,
  DialogTrigger,
  Heading,
  Icon,
  IconButton,
  Spinner,
  Text,
} from '@vega-ui/react';

Button Pending State

When to use:

  • an action is in progress and the button is temporarily disabled

Composition notes:

  • keep the spinner compact
  • disable the button while pending

Trade-offs:

  • clear immediate feedback
  • if text disappears entirely, context may be weaker
button-pending-state.tsx · 39 lines
import { Button, HelperText, Label, Spinner, TextField, TextFieldInput } from '@vega-ui/react';
import { CSSProperties, FormEvent, useId, useState } from 'react';

export default function ButtonPendingState() {
  const fieldId = useId();
  const [pending, setPending] = useState(false);
  const [message, setMessage] = useState('');

  const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    const data = new FormData(event.currentTarget);
    const workspace = String(data.get('workspace'));

Comparison

Quick Decision Rule

Use Spinner when a temporary pending state needs a compact animated indicator. Do not use it as a substitute for preserving layout or showing final status.

Spinner vs retained content

Use Spinner when:

  • progress is brief and the action is already obvious

Keep content in place when:

  • preserving layout matters more than motion

Spinner vs progress indicators

Use Spinner when:

  • exact progress is unknown

Use Progress when:

  • progress can be quantified

Choose This Component When

  • loading is indeterminate
  • a compact indicator is enough
  • the UI does not need to show a numeric or bar-like amount of completion

Do Not Choose This Component When

  • exact progress is known
  • the UI needs more context than a small animated ring can provide

Troubleshooting

Users Cannot Tell What Is Loading

Symptom

The spinner is visible, but users do not know which operation is pending.

Likely Cause

The spinner was rendered without contextual text or surrounding structure.

How To Verify

  • view the UI without knowing the implementation details
  • check whether the pending operation is obvious from nearby content

Fix

Pair the spinner with status text or place it inside an unmistakable pending surface.

The Spinner Feels Too Large Or Too Small

Symptom

The loading indicator looks visually unbalanced in its container.

Likely Cause

The numeric size does not match the surrounding control or surface.

How To Verify

  • compare the current size with adjacent text and controls

Fix

Use smaller sizes for inline and button contexts, and larger sizes for centered section loaders.

Motion Alone Is Carrying The Loading State

Symptom

Users who miss or cannot rely on motion do not get enough status information.

Likely Cause

The spinner is the only pending-state signal.

How To Verify

  • remove motion mentally and check whether any status text remains

Fix

Add nearby status text or a higher-level live region for meaningful asynchronous operations.