# Empty State

A ready-made empty state built on the Empty primitives with a dot-pattern backdrop, optional illustration icon, and action slot.

- Category: Data Display
- License: MIT
- Page: https://www.saasuji.com/components/empty-state
- Install: npx shadcn@latest add https://www.saasuji.com/r/empty-state.json

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| illustration | `"products" | "saved" | "rocket" | "search"` | — | Named icon shown in the icon media tile: package, bookmark, rocket, or search. |
| title | `string` | — | Primary heading; required. |
| description | `string` | — | Supporting copy rendered under the title. |
| action | `React.ReactNode` | — | Action node rendered in the content slot, typically a button or link. |
| className | `string` | — | Additional classes merged onto the Empty root. |

## Source

```tsx
"use client";

import { type ReactNode } from "react";
import { DotPattern } from "@/components/ui/dot-pattern";
import Package from "lucide-react/dist/esm/icons/package";
import Bookmark from "lucide-react/dist/esm/icons/bookmark";
import Rocket from "lucide-react/dist/esm/icons/rocket";
import SearchIcon from "lucide-react/dist/esm/icons/search";
import {
  Empty,
  EmptyContent,
  EmptyDescription,
  EmptyHeader,
  EmptyMedia,
  EmptyTitle,
} from "@/components/ui/empty";
import { cn } from "@/lib/utils";

const ICON_MAP = {
  products: Package,
  saved: Bookmark,
  rocket: Rocket,
  search: SearchIcon,
} as const;

type IllustrationType = keyof typeof ICON_MAP;

interface EmptyStateProps {
  illustration?: IllustrationType;
  title: string;
  description?: string;
  action?: ReactNode;
  className?: string;
}

export function EmptyState({
  illustration,
  title,
  description,
  action,
  className,
}: EmptyStateProps) {
  const Icon = illustration ? ICON_MAP[illustration] : null;

  return (
    <Empty
      className={cn(
        "relative text-center py-16 rounded-xl border border-dashed border-border overflow-hidden",
        className
      )}
    >
      <DotPattern
        width={20}
        height={20}
        cx={1}
        cy={1}
        cr={1}
        className="text-muted-foreground/20"
      />
      <EmptyHeader className="relative z-10">
        {Icon && (
          <EmptyMedia variant="icon">
            <Icon strokeWidth={1.2} />
          </EmptyMedia>
        )}
        <EmptyTitle>{title}</EmptyTitle>
        {description && <EmptyDescription>{description}</EmptyDescription>}
      </EmptyHeader>
      {action && <EmptyContent className="relative z-10">{action}</EmptyContent>}
    </Empty>
  );
}

```
