Components › States & feedback › Loading › Skeleton list

Skeleton list

canon

Ready-made loading body for listings: avatar circle, main line and a meta line, with aria-busy on the wrapper.

`.sk-card`/`.sk-kv` (kanban card and drawer composed skeletons) were unused and removed as dead code in acrm !4058 (28 Sep 2026); `SkeletonList` only ever emitted `.sk-task`.

Used in 69 files · 51 areas · 95× — components/accounting, components/agent-desk, components/ai-employees, components/calendar, components/company, components/deal …

The ready-made loading body for listings and tables that have no skeleton of their own: an avatar circle, a main line and a meta line pushed right. React packages/ui/src/components/Skeleton.tsx (SkeletonList), CSS apps/web/src/ds/skeleton.css.

Rule of states: loading = Skeleton, failed = ErrorState with a retry, nothing there = EmptyState. They never blend into one another.

When to use

  • A listing or a table that is loading for the first time and has no bespoke skeleton.
  • A panel or a rail section waiting for a short list.

When not to use

  • Paging or lazy-loading more rows into a list the user is already reading — that is list-loader in the footer.
  • A layout that differs substantially from "circle, line, meta" — then build the shape from skeleton-line and the other .sk-* primitives.
  • A record detail with no record — that is detail-state-screen.

Anatomy

  • Wrapper div[aria-busy="true"], a column with --sp-4 gaps and --sp-4 vertical padding.
  • Each row: optional .sk.sk-circle (22px) · a main SkLine · a sm SkLine pushed right with margin-left: auto.
  • rows (default 4) and avatar (default true) are the only knobs; the widths cycle through a fixed set so the column looks ragged like real text.

Measured: rows maps 1:1 to rendered children and to the number of circles.

Best practices

Do
  • Match rows to what the viewport actually shows — four for a listing above the fold, two in a panel, more only for a full page.
  • Turn avatar off for listings whose rows start with text.
  • Keep it inside the frame that is loading, with the top bar already drawn.
Don’t
  • Use it for a layout it does not resemble; a wrong-shaped skeleton is worse than none.
  • Leave it on screen after an error — swap to error-state.
  • Nest it inside another aria-busy region.

Content

None. Text next to a skeleton, if any, belongs to the host.

  • skeleton-line — the atom this is built from.
  • list-loader — the footer loader for paging.
  • empty-state, error-state — the two states that follow loading.
  • Stories: components--skeleton-list--default, --variants, --sizes, --states, --composition.

Source: docs/loading/skeleton-list.usage.md · GitLab