Skip to content

Skeleton

Placeholder shapes that stand in for content while it loads.

Preview

Installation

pnpm add @syntara/react @syntara/tokens
import { Skeleton, SkeletonText } from '@syntara/react';

Usage

import { Skeleton, SkeletonText } from '@syntara/react';

export function LoadingRow() {
  return (
    <div aria-busy="true">
      <Skeleton circle inlineSize={40} />
      <SkeletonText lines={2} />
    </div>
  );
}

Examples

Card

A loading card, marked aria-busy.

Text

SkeletonText follows the surrounding font size and line height.

Accessibility

No keyboard interaction of its own.

  • Skeletons are aria-hidden. Put aria-busy="true" on the loading region and announce completion if it matters.
  • The shimmer runs only under prefers-reduced-motion: no-preference and sweeps in the reading direction.

Guidelines

Do

  • Match the layout of the content that will replace it, so nothing jumps.
  • Use for loads longer than ~300ms.

Don’t

  • Don't skeleton things that never load (labels, headings you already know).
  • Don't mix skeletons and spinners for the same content.

API reference

Skeleton

inlineSize
number | string

Width. Numbers are pixels; strings are any CSS length.

Default '100%'

blockSize
number | string

Height. Numbers are pixels; strings are any CSS length.

Default '1em'

radius
  • fielddefault
  • container
  • pill
  • badge

Corner radius from the theme's shape tokens.

circle
boolean

A circle; inlineSize sets the diameter (default 40px).

Default false

SkeletonText

lines
number

Number of lines; the last one is 60% wide.

Default 3

Tokens

The semantic tokens this component reads, grouped by what they control. Swatches show this site’s theme; change a tenant’s brand and the component follows with no code change.

Colour1
text.default
Space and size1
space.10
Shape4
radius.badgeradius.containerradius.fieldradius.pill
Motion1
motion.duration.normal