EmptyState
UI primitive used to represent valid empty states with clear messaging and optional actions.
The EmptyState component represents a valid state with no data.
It explains why there is nothing to display and optionally guides the user toward the next action — without introducing product or business logic.
EmptyState is a pure UI primitive: it structures content, nothing more.
Import
import { EmptyState } from "@/components/ui/empty-state";Usage
Use EmptyState when a screen, section, or list has no content to display, but the application is otherwise in a valid state.
EmptyState should not be used for loading or error states.
Basic example
No projects yet
Create your first project to get started.
<EmptyState
title="No projects yet"
description="Create your first project to get started."
/>With action
EmptyState can optionally render a primary action (button or link).
No projects yet
Projects help you organize your work.
import { EmptyState } from "@/components/ui/empty-state";
import { Button } from "@/components/ui/button";
export function EmptyStateWithAction() {
return (
<EmptyState
title="No projects yet"
description="Projects help you organize your work."
action={<Button>Create project</Button>}
/>
);
}With icon
Use the icon slot for a simple decorative icon or illustration.
Nothing scheduled
Create an event to see it appear here.
<EmptyState
icon={<CalendarIcon className="h-6 w-6" aria-hidden />}
title="Nothing scheduled"
description="Create an event to see it appear here."
action={<Button variant="secondary">Create event</Button>}
/>Inside a Card
EmptyState composes naturally with surfaces such as Card.
No data available
Metrics will appear once data is collected.
import { Card, CardContent } from "@/components/ui/card";
import { EmptyState } from "@/components/ui/empty-state";
export function CardEmptyState() {
return (
<Card>
<CardContent className="p-6">
<EmptyState
title="No data available"
description="Metrics will appear once data is collected."
/>
</CardContent>
</Card>
);
}Table empty state
EmptyState works well inside data-heavy components such as Table (especially for filtered results).
No resultsTry adjusting your filters. |
import { Table, TableBody, TableRow, TableCell } from "@/components/ui/table";
import { EmptyState } from "@/components/ui/empty-state";
import { Button } from "@/components/ui/button";
export function TableEmptyState() {
return (
<Table>
<TableBody>
<TableRow className="hover:bg-transparent">
<TableCell colSpan={4} className="py-10">
<EmptyState
title="No results"
description="Try adjusting your filters."
action={
<Button variant="outline" size="sm">
Clear filters
</Button>
}
/>
</TableCell>
</TableRow>
</TableBody>
</Table>
);
}API
Props
| Prop | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Primary message explaining the empty state |
description | string | No | Additional context for the empty state |
action | React.ReactNode | No | Optional action (button, link, etc.) |
icon | React.ReactNode | No | Optional icon or illustration |
className | string | No | Additional Tailwind classes |
EmptyState also accepts all standard HTML div props:
React.HTMLAttributes<HTMLDivElement>Accessibility
- Rendered with
role="status"to announce informational state changes. - Content remains readable without icons.
- Actions are fully keyboard accessible.
- No focus is forced when the empty state appears.
- Avoid using EmptyState to announce errors (use Alert for that).
Design guidelines
- Always explain why the state is empty (not just “Nothing here”).
- Keep titles short and descriptive.
- Use actions sparingly — one primary action is usually enough.
- Avoid product-specific language inside the component; pages and patterns decide what happens next.
- Keep the empty state aligned with surrounding density (use
Card/Tablewrappers as needed).
When not to use EmptyState
Do not use EmptyState for:
- Loading states → use Skeleton
- Error states → use Alert
- Onboarding flows (use dedicated onboarding screens)
- Blocking or modal interactions (use Dialog / Sheet patterns)