Design System

Skeleton

A loading state for a component to display an animated placeholder in place of the component, to convey data is being fetched and prevent layout shift.

React


import { Skeleton } from '@hover/blueprint';

Usage

You can use it as a standalone component.

live

<Stack>
<Skeleton height="20px" />
<Skeleton height="20px" />
<Skeleton height="20px" />
</Stack>

Or to wrap another component to take the same height and width.

live

<Skeleton>
<div>contents wrapped</div>
<div>won't be visible</div>
</Skeleton>

Useful when fetching remote data.


import { Box } from '@hover/blueprint';
const Card = () => {
const { data, loading, error } = useRemoteData();
if (error) return <Box children="error" />;
return (
<Box>
<Skeleton isLoaded={!loading}>
<Heading>{data.title}</Heading>
</Skeleton>
</Box>
);
};

Color mode

By default, Skeleton uses the color mode context to determine whether to display a dark or light placeholder animation. Pass colorMode to manually force a color mode.

live

<Stack>
<Stack padding="500" background="neutral.0" borderRadius="300">
<Skeleton colorMode="light" height="300" />
</Center>
<Stack padding="500" background="neutral.875" borderRadius="300">
<Skeleton colorMode="dark" height="300" />
</Center>
</Stack>

Displaying content once loaded

You can prevent the skeleton from rendering using the isLoaded prop.


<Skeleton isLoaded>
<span>Content has been loaded</span>
</Skeleton>

Fade duration

With the fadeDuration prop, you can control the duration of the content fading into view. The value in this prop is a number representing seconds which is part of the animation style prop that is rendered to the component. The default value is 0.4 seconds.

This requires the isLoaded prop, and the animation is best visible when the isLoaded prop is toggled to true.

live

() => {
const [isLoaded, { toggle }] = useBoolean(false);
return (
<Stack spacing="300">
<Skeleton isLoaded={isLoaded}>
<Center background="primary.500" borderRadius="200" padding="300">
<Body as="span" isBold color="neutral.0">
Default
</Body>
</Center>
</Skeleton>
<Skeleton isLoaded={isLoaded} fadeDuration={1}>
<Center background="secondary.500" borderRadius="200" padding="300">
<Body as="span" isBold color="neutral.0">
1 Second
</Body>
</Center>
</Skeleton>
<Skeleton isLoaded={isLoaded} fadeDuration={4}>
<Center background="danger.500" borderRadius="200" padding="300">
<Body as="span" isBold color="neutral.0">
4 Seconds
</Body>
</Center>
</Skeleton>
<Button onClick={toggle}>Toggle</Button>
</Stack>
);
};


Copyright © 2025 Hover Inc. All Rights Reserved.