Loading

Signals an indeterminate wait: a spinner, dots, a pulse, bars, a matrix or a shimmer.

import { Loading } from "@usefragments/ui";Source

Preview

<Loading label="Loading findings" />

Usage

Use when

  • Waiting on an async action where the result will appear
  • The first paint of an app (Loading.Screen)
  • A short wait inside a line of text (inline)
  • An assistant writing a reply (dots), a live session listening (pulse), audio or a stream arriving (bars), work being assembled such as a build or a generated screen (matrix)
  • The step an agent is on, in words: "Searching the codebase…" (shimmer)

Avoid when

  • You know the percentage: use Progress
  • You know the shape of the result: use Skeleton
  • An assistant working on a reply: use ThinkingIndicator

Implementation notes

  • One size, 16px or the line's own (inline); every kind takes the ink of whatever it sits in
  • Pick the kind by what is happening, not for variety: spinner by default, the others where they say more
  • Nothing shows for the first second; work that finishes sooner shows nothing
  • Dim the content in place rather than covering it
  • Name the wait in the label: "Loading findings", not "Loading"

Installation

pnpm add @usefragments/ui

Import styles once from @usefragments/ui/styles. See the installation guide for framework and theme setup.

Anatomy

Import Loading once, then compose its parts with dot notation.

  • Loading.Screen

Examples

Kinds

Six ways to draw a wait, each for a different kind of work.

import { Stack } from '@usefragments/ui';

<Stack direction="row" gap="xl" align="center" wrap>
  <Loading delay={0} label="Loading findings" />
  <Loading kind="dots" delay={0} label="Writing a reply" />
  <Loading kind="pulse" delay={0} label="Listening" />

Agent at work

The shimmer names the step; it changes as the work moves on.

<Loading kind="shimmer" delay={0} label="Searching 214 files for raw colour values…" />

Typing

Dots where the reply will appear, until its first words arrive.

import { Message } from '@usefragments/ui';
import { Stack } from '@usefragments/ui';

<Stack gap="md">
  <Message from="user">
    <Message.Content>Which screens still use raw colours?</Message.Content>

Live session

A pulse while a session listens, bars while a voice comes in. The status names the state, so the visible words are hidden from screen readers.

import { Stack } from '@usefragments/ui';
import { Text } from '@usefragments/ui';

<Stack gap="sm">
  <Stack direction="row" gap="sm" align="center">
    <Loading kind="pulse" delay={0} label="Listening" />

Assembling

The matrix while a build or a generated screen comes together: light crosses the grid until the result replaces it.

import { Stack } from '@usefragments/ui';
import { Text } from '@usefragments/ui';

<Stack direction="row" gap="sm" align="center">
  <Loading kind="matrix" delay={0} label="Generating the settings screen" />
  <Text color="secondary" aria-hidden="true">Generating the settings screen</Text>

Inline

Sized to the text it sits in.

<p>
  Checking the request <Loading inline label="Checking the request" />
</p>

Fill

Fills the slot the result will take and centres in it.

<div style={{ height: 120 }}>
  <Loading fill label="Loading the chart" />
</div>

Screen

The whole view is waiting on first paint.

<Loading.Screen label="Opening the workspace" showLabel />

API reference

Component props
Prop
Type
Default
Description
delaynumber | undefined1000Milliseconds of quiet before the spinner shows; 0 when the caller already waited
fillboolean | undefinedfalseFill the parent and centre the spinner in it
inlineboolean | undefinedfalseSize the spinner to the surrounding text (1em) so it sits inside a line
kindLoadingKind | undefinedspinnerdotspulsebarsmatrixshimmerspinnerHow the wait is drawn: spinner where a result will appear, dots while a reply is written, pulse while something live listens or connects, bars while a stream or voice comes in, matrix while work is assembled, shimmer shows the label with the working sheen
labelstring | undefined"Loading…"What is loading, read by screen readers
Screen.delaynumber | undefinedNot setMilliseconds of quiet before the spinner shows.
Screen.labelstring | undefinedNot setWhat is loading.
Screen.showLabelboolean | undefinedNot setShow the label under the spinner as well as reading it.

Accessibility

  • role="status" with the label as its name and as hidden text once the spinner shows
  • The spinner keeps turning under reduced motion: it is progress, not decoration
  • Under reduced motion the dots, pulse and bars stop moving and only fade in turn; the matrix only ever fades, so it runs as it is; the shimmer holds still in ink 3

Next steps