XDSSkeleton@xds/core · Skeleton

Usage

An animated shimmer placeholder that previews the shape of content while it loads. Use it to build loading screens that match the layout of the real content. For content with unknown dimensions, use Spinner instead.

Best practices

GuidancePractices
DoMatch the size and shape of the content being loaded to create a realistic placeholder.
DoStagger multiple skeletons with the `index` prop for a natural wave animation.
Don'tUse when the content dimensions are unknown — use Spinner instead.
Don'tCombine with a Spinner on the same content area — pick one loading pattern.
Don'tShow skeletons indefinitely — if loading takes too long, show an error or empty state instead.

Import

ts
import {XDSSkeleton} from '@xds/core/Skeleton'

Props

PropTypeDescription
width
number | string (default: '100%')Width in pixels (number) or CSS value (string).
height
number | string (default: '100%')Height in pixels (number) or CSS value (string).
radius
'none' | 0 | 1 | 2 | 3 | 4 | 'rounded' (default: 3)Border radius using design token scale. Use none for sharp corners, rounded for fully rounded (avatars, pills, circles).
index
number (default: 0)Index for staggered animation timing. For element at index n, animation starts at DELAY_TIME + (STAGGER_TIME × n).

Examples

Common configurations, variations, and states.
Skeleton — Card LoadingCard skeleton with avatar, name, and content lines.
tsx
'use client';
import {XDSSkeleton} from '@xds/core/Skeleton';
import {XDSCard} from '@xds/core/Card';
import {XDSHStack, XDSVStack} from '@xds/core/Layout';
export default function SkeletonCardSkeleton() {
return (
<XDSCard width={320}>
<XDSVStack gap={3}>
<XDSHStack gap={3} vAlign="center">
<XDSSkeleton width={40} height={40} radius="rounded" index={0} />
<XDSVStack gap={1}>
<XDSSkeleton width={120} height={14} index={1} />
<XDSSkeleton width={80} height={12} index={2} />
</XDSVStack>
</XDSHStack>
<XDSSkeleton width="100%" height={14} index={3} />
<XDSSkeleton width="90%" height={14} index={4} />
<XDSSkeleton width="75%" height={14} index={5} />
</XDSVStack>
</XDSCard>
);
}
Skeleton — Staggered ListStaggered skeleton lines with varying widths.
tsx
'use client';
import {XDSSkeleton} from '@xds/core/Skeleton';
import {XDSVStack} from '@xds/core/Layout';
export default function SkeletonStaggeredList() {
return (
<XDSVStack gap={2}>
<XDSSkeleton width={300} height={16} index={0} />
<XDSSkeleton width={280} height={16} index={1} />
<XDSSkeleton width={320} height={16} index={2} />
<XDSSkeleton width={260} height={16} index={3} />
<XDSSkeleton width={290} height={16} index={4} />
</XDSVStack>
);
}
Skeleton — Table RowsTable skeleton with staggered column widths.
tsx
'use client';
import {XDSSkeleton} from '@xds/core/Skeleton';
import {XDSHStack, XDSVStack} from '@xds/core/Layout';
export default function SkeletonTableRowSkeleton() {
return (
<XDSVStack gap={2}>
{[0, 1, 2, 3].map(rowIndex => (
<XDSHStack key={rowIndex} gap={4} vAlign="center">
<XDSSkeleton width={50} height={16} index={rowIndex * 4} />
<XDSSkeleton width={180} height={16} index={rowIndex * 4 + 1} />
<XDSSkeleton width={100} height={16} index={rowIndex * 4 + 2} />
<XDSSkeleton width={80} height={16} index={rowIndex * 4 + 3} />
</XDSHStack>
))}
</XDSVStack>
);
}

Showcase source

tsx
'use client';
import {XDSSkeleton} from '@xds/core/Skeleton';
export default function SkeletonShowcase() {
return <XDSSkeleton width={200} height={20} radius={3} />;
}