Skeleton
Loading placeholder — a fixed rectangular/circular shape, or a wrap mode that sizes itself to real children and reveals them once loaded.
Skeleton is a loading placeholder. Standalone, it's a fixed rectangular or circular shape; wrapped around real content, it sizes itself to that content's own box and reveals it once loading finishes. DataTable's own skeleton rows and cards render through this component internally.
import { Skeleton } from '@42/ui-react/skeleton';
<Skeleton />
<Skeleton shape="circular" width={40} height={40} />
<Skeleton loading={isLoading}>
<UserAvatar user={user} />
</Skeleton>Playground
Component
Dir
Presets
Props
Code
<Component shape="rectangular" size="md" />Full prop browser
Shapes
Two shapes: rectangular (the default — fills its container's width) and circular (a fixed-diameter dot).
Code
<Skeleton shape="rectangular" /><Skeleton shape="circular" />Sizes
size steps through the kit's shared xs–xl scale — the same steps DataTable's own density prop uses, so a skeleton bar matches whatever table density it stands in for. It's tuned for text-line bars (8–24px tall); for a bigger shape like an avatar circle, use width/height instead (see Recipes).
Code
<Skeleton size="xs" /><Skeleton size="sm" /><Skeleton size="md" /><Skeleton size="lg" /><Skeleton size="xl" />Wrap mode
Pass children and Skeleton sizes a placeholder to match — no measurement, no ResizeObserver: the real content stays mounted (just made invisible) while loading, so it keeps contributing its own box to the wrapper the placeholder fills. Click below to see the same Skeleton instance swap live between the placeholder and the real content it's wrapping — "Reveal" flips loading to false, "Reset" flips it back.
Code
function Demo() { const [loading, setLoading] = useState(true); return ( <> <Button size="sm" variant="light" color="gray" onClick={() => setLoading((v) => !v)}> {loading ? 'Reveal' : 'Reset'} </Button> <Skeleton loading={loading}> <span className="text-sm">Real content, revealed once loaded</span> </Skeleton> </> );}The overlay's shape/size still come from those props, same as standalone mode — only the placeholder's dimensions are inferred from the child, not its shape (a circular avatar's wrapper won't automatically become a circular placeholder; pass shape="circular" for that too).
The wrapper shrink-wraps to the content's own intrinsic size — content that itself stretches to fill its container (w-full, flex-1, an unconstrained block paragraph) won't get a full-width overlay from wrap mode alone. Add className="block w-full" in that case, or fall back to standalone mode with an explicit width.
Recipes
Skeleton has no layout logic of its own — complex, card-style loading states are built by composing plain shapes inside the kit's existing Card and Flex/Grid. This is exactly the pattern DataTable's stacked-card loading view uses internally.
Rectangle
Code
<Skeleton size="sm" /><Skeleton size="md" className="w-2/3" />Circle
Code
<Skeleton shape="circular" width={40} height={40} />Card stack — DataTable's own stacked skeleton pattern
Code
<Card padding="sm"> <Flex gap="sm" align="center"> <Skeleton shape="circular" width={40} height={40} /> <Flex direction="col" gap="xs" className="flex-1"> <Skeleton size="sm" className="w-1/3" /> <Skeleton size="xs" className="w-2/3" /> </Flex> </Flex></Card>API
Prop
Type
All other props are forwarded to the root <div>.
Accessibility
A standalone placeholder is aria-hidden — it's a visual stand-in with nothing for assistive tech to announce. In wrap mode, the wrapper carries aria-busy/data-loading while loading, and the real (still-mounted, invisible) content is hidden from assistive tech until it's revealed. The pulse animation respects prefers-reduced-motion (motion-reduce:animate-none) — an improvement DataTable's own pre-existing skeleton bars didn't have before adopting this component.