A skeleton component displays a placeholder while content is loading.
With shimmer border
Installation
Copy and paste the following code into your project.
import { cn } from '@kit/shared';
export interface SkeletonProps {
/**
* Disable the shimmer animation.
*
* @default false
*/
noShimmer?: boolean;
/**
* Display an animated shimmer border.
*
* @default false
*/
shimmerBorder?: boolean;
/**
* Used by the extra wrapper added when `shimmerBorder` is true
*/
shimmerBorderClassName?: string;
}
function Skeleton({
className,
noShimmer = false,
shimmerBorder = false,
shimmerBorderClassName = '',
style: styleProps,
...props
}: SkeletonProps & React.ComponentProps<'div'>) {
const {
animationDelay,
} = styleProps || {};
const content = (
<div
data-slot="skeleton"
className={cn(
'bg-accent rounded-md',
noShimmer
? 'animate-pulse'
: 'animate-shimmer shimmer-with-pulse [--shimmer-color:color-mix(in_oklab,var(--color-opposite)_8%,transparent_100%)] dark:[--shimmer-color:color-mix(in_oklab,var(--color-opposite)_3%,transparent_100%)]',
className
)}
aria-label="Loading"
style={styleProps}
{...props}
/>
);
return shimmerBorder && !noShimmer ? (
<div
className={cn(
'animate-shimmer rounded-[9px] p-px [--shimmer-color:color-mix(in_oklab,var(--color-opposite)_40%,transparent_100%)]',
shimmerBorderClassName
)}
style={{animationDelay}}
>
<div className="bg-background rounded-md ">{content}</div>
</div>
) : (
content
);
}
export { Skeleton };
Add the required shimmer animation styles to your globals.css file:
/* shimmer animation */ @keyframes shimmer-animation { 0% { background-position: var(--shimmer-start-x, -1000px) 0; } 100% { background-position: var(--shimmer-end-x, 1000px) 0; } } @theme { --animate-shimmer: shimmer-animation 2s linear infinite; } @utility shimmer-with-pulse { animation: shimmer-animation 2s linear infinite, var(--animate-pulse, pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite); } @utility animate-shimmer { --_shimmer-center: var(--shimmer-center, 0.65); /* 0.5 centered */ --_shimmer-width: var(--shimmer-width, 200px); --_shimmer-color: var( --shimmer-color, color-mix(in oklab, var(--color-opposite) 3%, transparent 100%) ); --_reference: 50%; --_shimmer-half-width: calc(var(--_shimmer-width) / 2); --_lower-breakpoint: calc(var(--_reference) - var(--_shimmer-half-width)); --_upper-breakpoint: calc(var(--_reference) + var(--_shimmer-half-width)); --_main-breakpoint: calc(var(--_lower-breakpoint) + var(--_shimmer-width) * var(--_shimmer-center)); background-image: linear-gradient( 110deg, transparent 0%, transparent var(--_lower-breakpoint), var(--_shimmer-color) var(--_main-breakpoint), transparent var(--_upper-breakpoint), transparent 100% ); background-size: cover; background-repeat: no-repeat; }
Update the import paths to match your project setup.
Usage
import { Skeleton } from '@kit/ui/skeleton';<Skeleton className="w-48 h-4" />Custom Shimmer Color
Customize the shimmer color using the --shimmer-color CSS variable:
API Reference
| Prop | Type | Default |
|---|---|---|
noShimmer | boolean | false |
shimmerBorder | boolean | false |
shimmerBorderClassName | string |
Ratio Preserver
A component that maintains aspect ratio and scales content to fit any viewport size while preserving proportions.
Speech Input
A compound component for capturing and transcribing audio input using the Web Speech API with real-time visualization.
How is this guide?
Last updated on 11/26/2025