Components
A composable empty-state block for when there's no data to show — no results, no events, an empty folder, cleared filters. Ships Empty plus EmptyHeader, EmptyMedia (with a stacked 'icon' variant), EmptyTitle, EmptyDescription and EmptyContent, so you can drop in an icon or illustration, a title, supporting copy and call-to-action buttons. Dependency-free (just cva + cn).
Loading preview...
import {
Empty,
EmptyDescription,
EmptyHeader,
EmptyMedia,
EmptyTitle,
} from "@/components/ui/cnippet-empty";
function StackedCardsIllustration() {
return (
<div aria-hidden="true" className="relative h-24 w-52">
{/* Back card */}
<div className="absolute inset-x-6 top-0 h-6 rounded-t-lg border border-border/50 bg-muted/60 dark:bg-muted/30" />
{/* Middle card */}
<div className="absolute inset-x-3 top-3 h-6 rounded-t-lg border border-border/60 bg-muted/80 dark:bg-muted/50" />
{/* Front card */}
<div className="absolute inset-x-0 top-6 flex h-16 items-center gap-3 rounded-lg border border-border bg-background px-4 shadow-sm">
<div className="size-8 shrink-0 rounded bg-muted" />
<div className="flex flex-1 flex-col gap-1.5">
<div className="h-2.5 w-3/4 rounded bg-muted" />
<div className="h-2 w-1/2 rounded bg-muted/60" />
</div>
</div>
{/* Fade overlay */}
<div className="pointer-events-none absolute inset-x-0 bottom-0 h-8 bg-linear-to-b from-background/0 via-background/60 to-background" />
</div>
);
}
export default function EmptyProducts() {
return (
<div className="flex items-center justify-center p-4">
<Empty className="py-12">
<EmptyHeader>
<EmptyMedia>
<StackedCardsIllustration />
</EmptyMedia>
<EmptyTitle>No products</EmptyTitle>
<EmptyDescription>
No data here yet. We will notify you when there's an update.
</EmptyDescription>
</EmptyHeader>
</Empty>
</div>
);
}
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...