Skeleton

Show pulsing loading placeholders, either as a grid of cards or a single block.

Skeleton is a client component ("use client") that renders animated Placeholder blocks using motion/react. Use it while content loads. The grid variant lays them out in a Collection; the component variant renders a single placeholder.

Loading...
Loading...
Loading...

Import#

typescript
import { Skeleton } from "@reactberry/system/blocks";

Usage#

typescript
import { Collection, Skeleton } from "@reactberry/system/blocks";
import { Box, Text } from "@reactberry/system/elements";

type Project = { id: string; name: string };

export default function ProjectGrid({ projects }: { projects?: Project[] }) {
  if (!projects) return <Skeleton count={6} colsize="medium" aspect="4/3" />;

  return (
    <Collection colsize="medium">
      {projects.map((project) => (
        <Box key={project.id} skin="surface" shape="rounded" p="m">
          <Text>{project.name}</Text>
        </Box>
      ))}
    </Collection>
  );
}

Examples#

Single block#

Use variant="component" for one placeholder, such as a value that is still loading. Set its size with width and height.

Account balance

List rows#

colsize="row" gives a single column. A wide aspect and showText={false} make the placeholders look like list rows.

API#

Skeleton#

PropTypeDefaultDescription
count
number
9

Number of placeholders (grid only).

aspect
string
3/2

Aspect ratio of each placeholder (grid only).

colsize
"small""auto""medium""row""large""xlarge""xxlarge"
"xlarge"

Column size passed to Collection (grid only).

showText
boolean
true

Renders "Loading..." inside each placeholder (grid only).

variant
"grid""component"
"grid"

Layout mode: a grid of placeholders or a single block.

width
string
100%

Placeholder width (component only).

height
string
2.25rem

Placeholder height (component only).

All other props are spread onto each Placeholder (not onto the Collection), after the defaults.

Accessibility#

  • No aria-busy or live-region attributes are set. Mark the loading region yourself if needed.
  • The "Loading..." text is rendered once per placeholder in the grid variant, so a screen reader may read it several times. Use showText={false} and label the region instead.

Notes#

  • Each placeholder uses bg="transparent.light.0", shape="rounded", the IconDotsAnim icon, and a 1.5s infinite opacity pulse (0.5 to 1 to 0.5).
  • In the component variant, count, aspect, colsize and showText are ignored. In the grid variant, width and height are ignored.
  • Because extra props go to every placeholder, layout props such as gap or mb cannot be applied to the grid container; wrap the Skeleton in a Box instead.
  • The pulse does not respect prefers-reduced-motion.