Skip to content

Components · Status and feedback

LoadingState

A region is loading: a layout-shaped skeleton or a labelled spinner, announced once.

@rookcom/monarch-reactComponent

List and rows

Loading contacts
Loading invoices

Usage examples

Cards and detail

Spinner

Purpose

The placeholder shown while a list, table, card grid or detail view loads. It marks the region busy and announces what is loading once.

Use when

  • A list with avatars is loading (list, the default).
  • A table or plain list is loading (rows).
  • A card grid is loading (cards).
  • A detail view is loading (detail).
  • The shape of the result is unknown, or a whole card or page is loading (spinner).

Avoid when

  • A single control is busy: use Button loading or Spinner.
  • Loading failed: use ErrorState or InlineErrorRetry.
  • There is no data: use EmptyState.

Design principles

  • Match the shape of what is coming, so the page does not jump when it arrives.
  • Announce the label once and hide the skeleton shapes from assistive technology.
  • A spinner always comes with visible text naming what is loading; never a bare spinner on a page.

API reference

import { LoadingState } from '@rookcom/monarch-react';
ExportKindRenderingRoot class
LoadingStatecomponentserver-safe.mn-loading-state

All native <div> attributes pass through, and the ref is forwarded to the root <div>.

Before 0.4 LoadingState lived in the error-state folder; the export, props and class names (mn-loading-state, __row, __lines) are unchanged.

Generated from the TypeScript declarations of packages/react/src/components/feedback/loading-state.

Properties

LoadingState

Skeleton placeholder with an aria-busy region and a live announcement.

PropTypeDescription
label requiredstringAnnounced to screen readers, e.g. "Loading tickets".
childrenReactNode
classNamestring
idstring
rowsnumberSkeleton rows to render (`list`, `rows` and `cards`). Default 4.
variantLoadingStateVariant`list` (default) stacks avatar + text rows; `rows` stacks plain text rows (table and list-row preset); `cards` renders a grid; `detail` a title + paragraphs; `spinner` a centred spinner with the label shown.

Variants

PropValuesDescription
variant'list''rows''cards''detail''spinner'list (default) stacks avatar + two text lines; rows stacks bordered text rows (table and list-row preset); cards a grid of blocks; detail a title and paragraphs; spinner a centred spinner with the label shown. Exposed as data-variant.
rows'number'Rows for list, rows and cards. Default 4; negative values render none.

States

StateExposed asBehaviour
Loadingaria-busy="true"The root is always marked busy; unmount it when the content arrives.

Interaction behaviour

Not interactive.

Keyboard support

Not interactive and not focusable.

Accessibility

Role
status inside an aria-busy region
Accessible name
The label prop, e.g. "Loading invoices".
  • The label renders in a role="status" element: visually hidden for skeleton variants, visible next to the spinner for spinner.
  • Skeleton shapes and the spinner are aria-hidden.
  • Do not nest LoadingState inside another aria-busy region; announce completion from the loaded content if it matters.
  • Verified with axe in jsdom and in Chromium, Firefox and WebKit on /components/loading-state.

Responsive behaviour

  • cards uses an auto-fill grid with a 14rem minimum column that shrinks to one full-width column below 14rem.
  • Skeleton widths are percentages, so rows fit any container down to 320px.

Theme support

  • Skeleton shapes use the Skeleton component (muted surface tokens); rows dividers use --mn-color-border-subtle.
  • The spinner label uses --mn-color-text-muted.
  • Under prefers-reduced-motion: reduce the skeleton shimmer stops and the spinner slows (from Skeleton and Spinner).

Do and don't

Do

  • Give it a label naming what is loading.
  • Pick the variant that matches the content that will replace it.

Don't

  • Do not nest LoadingState inside another aria-busy region.
  • Do not leave it mounted after the content arrives.

Dependencies

KindDepends on
npm packagesreact
Monarch componentsSkeleton, Spinner

Testing coverage

  • Announces its label as a status inside an aria-busy root.
  • Default props keep the 0.3 markup and class names; the ref is forwarded.
  • rows renders plain text rows without avatars; cards and detail render their shapes.
  • spinner shows the label as visible status text and hides the spinner from assistive technology.
  • Negative rows render no rows.
CheckCovered
Axe in jsdomYes
Server renderingYes
Browser suitesVisual baselines: /__gallery; Cross-browser axe: /components/loading-state

Tests: packages/react/src/components/feedback/loading-state