Skeleton

The shape of the content before the content arrives, so the layout does not move when it does.

Code

antuikit's Skeleton is Ant Design's Skeleton and its five element placeholders, installed into your project as a file you own. It adds no behavior and no styling, and every prop passes through. Its SkeletonProps adds children and a ref to SkeletonRef to the type, both marked antuikit in the API table below.

Install

npx antuikit@latest init
npx antuikit@latest add skeleton
The first command installs AntuikitProvider and the kit's theme, and the second adds this component.

Import

From @/components/ui/skeleton, not from antd. The file is yours once it is installed, so the import path is a path in your project.
import { Skeleton } from "@/components/ui/skeleton"

The five shapes

Beside the text block, Skeleton has five element placeholders, and the kit wraps all five. Each one reserves space for one kind of control.
1
<Skeleton.Button size="large" shape="round" active />
2
<Skeleton.Input size="small" block active />
3
<Skeleton.Avatar size={64} shape="circle" active />
4
<Skeleton.Image />
5
<Skeleton.Node style={{ width: 240, height: 160 }} active>
6
<ChartGlyph />
7
</Skeleton.Node>
Each is also exported by name, so the compound form and the named form are the same component:
import {
Skeleton,
SkeletonAvatar,
SkeletonButton,
SkeletonImage,
SkeletonInput,
SkeletonNode,
} from "@/components/ui/skeleton"
Skeleton.Image draws its own picture glyph, so skeleton.json declares no icon pack and switching packs does not change it. Skeleton.Node holds a shape the other four do not cover: a chart, a map, a video frame. Neither takes size or shape, and className lands on the outer element, so size the gray box with classNames.content or style.

Sizes and shapes

Skeleton has no variant prop, and the kit adds none. You set up the root by what you turn on and how many lines you ask for.
The options belong to the five elements, and they differ from one to the next:
  • Skeleton.Avatar takes size (small, medium, large or a number) and a shape of circle or square, defaulting to circle.
  • Skeleton.Button takes size without the number, and the full shape set: circle, square, round, default.
  • Skeleton.Input takes size only. It has no shape.
  • Skeleton.Image and Skeleton.Node take neither, and passing one does nothing.
Where size is not set, it follows the size set on a parent ConfigProvider, so a Skeleton inside a compact region follows it. size="default" is deprecated and warns in development. Write medium.

Flags

Three booleans on the root, each one behavior.
  • active runs the shimmer, a gradient swept across the bars on repeat. On the root it drives the avatar, the title and the paragraph together. The five elements each take their own. It does not check prefers-reduced-motion, so gate it yourself.
  • loading is the switch. Leave it out and the placeholder always shows, which is why a Skeleton with no loading still shows bars. Pass false and it renders its children, or nothing when there are none.
  • round turns the title and the body lines into capsules. It does not follow the theme's borderRadius, and an avatar beside the bars keeps its own shape.
Skeleton.Button and Skeleton.Input take a fourth, block, which stretches the element to the width of its parent.

Slots

Skeleton has one, children, and it holds the real content. The kit's SkeletonProps types it, so your editor knows about it. The placeholder stands in for the children while loading is true and gives way once it is false: one component at the call site, no branch.
1
<Skeleton loading={isPending} avatar paragraph={{ rows: 2 }}>
2
<ProfileCard user={data} />
3
</Skeleton>
Skeleton.Node is the other one: whatever you pass renders inside the gray box. Skeleton.Image is a Node with the picture glyph already inside, so it takes no children.
The title and the paragraph are not slots. You describe them with data (rows, width), so there is nothing to render into them.

Events

Skeleton has no event handlers of its own. What it forwards to the element it renders is in the API table below.

Styling

Skeleton names its parts, and classNames and styles take the same keys. Style a part through its key before reaching for a descendant selector, since the keys stay stable across versions.
1
<Skeleton
2
classNames={{
3
root: "…",
4
header: "…",
5
section: "…",
6
avatar: "…",
7
title: "…",
8
paragraph: "…",
9
}}
10
/>

API Reference

Skeleton
Skeleton's props. Rows marked antuikit in the Version column are added by the kit.
SkeletonTitleProps
SkeletonTitleProps's props.
SkeletonParagraphProps
SkeletonParagraphProps's props.
Skeleton.Avatar
Skeleton.Avatar's props.
Skeleton.Button
Skeleton.Button's props.
Skeleton.Input
Skeleton.Input's props.
Skeleton.Image
Skeleton.Image's props.
Skeleton.Node
Skeleton.Node's props.