A pulsing placeholder block for loading states. The simplest component in this bundle — one div, no Radix, no variant/size prop.
npx chandra-asri-ui add skeletonimport { Skeleton } from "@/app/components/ui/skeleton";
export function SkeletonDemo() {
return (
<div className="flex items-center gap-4">
<Skeleton className="h-12 w-12 rounded-full" />
<div className="flex flex-col gap-2">
<Skeleton className="h-4 w-48" />
<Skeleton className="h-4 w-32" />
</div>
</div>
);
}
No built-in shape or size — every placeholder (text line, avatar circle, image block) is a one-off className at the call site, e.g. <Skeleton className="h-32 w-32 rounded-full" /> for a circular avatar placeholder. The source platform's own skeleton uses bg-gray-200 (plain Tailwind gray, off-brand) — this one uses bg-surface-alt instead, the brand-token equivalent the source's own style guide flags as the correct fix.
import { cn } from "@/lib/utils";
import type { HTMLAttributes } from "react";
/**
* Pulsing placeholder block for loading states. Size it with className
* (e.g. `h-4 w-32`, `h-48 w-full`) — it has no intrinsic dimensions.
*/
export function Skeleton({
className,
...props
}: HTMLAttributes<HTMLDivElement>) {
return (
<div
className={cn("bg-surface-alt animate-pulse rounded-md", className)}
{...props}
/>
);
}