# Skeleton

Reserve space while application content loads.

Member row placeholder

[Complete TSX file](/examples/skeleton/default.tsx)

```tsx
"use client";

import { Skeleton } from "@/siteplane/components/skeleton";

export default function Example() {
  return (
    <div aria-busy="true" className="flex w-full max-w-92 items-center gap-4">
      <Skeleton aria-hidden="true" className="size-10 rounded-full" />
      <div aria-hidden="true" className="flex flex-1 flex-col gap-1">
        <Skeleton className="h-4 max-w-54" />
        <div className="flex max-w-54 gap-1">
          <Skeleton className="h-4 w-1/2" />
          <Skeleton className="h-4 w-1/2" />
        </div>
      </div>
      <Skeleton aria-hidden="true" className="h-8 w-20" />
      <span className="sr-only" role="status">
        Loading member
      </span>
    </div>
  );
}
```

## Installation

Complete [one-time setup](/docs/installation/) first.

```bash
pnpm dlx shadcn@4.18.0 add @siteplane/skeleton
```

With npm: `npx shadcn@4.18.0 add @siteplane/skeleton`. [Registry JSON](/registry/skeleton.json) lists source files and dependencies.

For this page’s examples, also install:

```bash
pnpm dlx shadcn@4.18.0 add @siteplane/card
```

## Usage

```tsx
import { Skeleton } from "@/siteplane/components/skeleton";

<Skeleton className="h-5 w-40" />;
```

## Card

Mirror the structure of the card that is loading, so the layout does not shift when the content arrives.

Project card placeholder

[Complete TSX file](/examples/skeleton/card.tsx)

```tsx
"use client";

import { Card, CardHeader, CardPanel } from "@/siteplane/components/card";
import { Skeleton } from "@/siteplane/components/skeleton";

export default function Example() {
  return (
    <Card aria-busy="true" className="w-full max-w-md">
      <CardHeader aria-hidden="true">
        <Skeleton className="h-4 w-2/3" />
        <Skeleton className="h-4 w-1/2" />
      </CardHeader>
      <CardPanel aria-hidden="true">
        <Skeleton className="aspect-video w-full" />
      </CardPanel>
    </Card>
  );
}
```

## Table

Repeat row placeholders sized like the expected columns while table data loads.

Table rows placeholder

[Complete TSX file](/examples/skeleton/table-row.tsx)

```tsx
"use client";

import { Skeleton } from "@/siteplane/components/skeleton";

const rows = [1, 2, 3, 4, 5];

export default function Example() {
  return (
    <div aria-busy="true" className="flex w-full max-w-sm flex-col gap-2">
      {rows.map((row) => (
        <div key={row} aria-hidden="true" className="flex gap-4">
          <Skeleton className="h-4 flex-1" />
          <Skeleton className="h-4 w-24" />
          <Skeleton className="h-4 w-20" />
        </div>
      ))}
    </div>
  );
}
```

## API reference

`Skeleton` accepts native `div` props, children and refs. `className` adds dimensions and shape to the rounded animated surface. There are no size, variant, loading or data props; an empty skeleton has no useful height until you supply it. Native attributes follow [HTML div](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/div).

[Read the installed source](/source/skeleton).

## Usage notes

Size the placeholders for the expected content and hide them from assistive technology. The surrounding region owns busy state and the loading announcement, as in the first example. Remove placeholders when data settles, then show real content, an empty state or an error. The shared motion stylesheet handles the skeleton animation; do not communicate progress through animation alone.
