Empty State
ProThe zero-data, no-results and first-run placeholder. A neutral icon tile, a balanced title, a readable description and a single outline action, composed from named parts, with a density axis for in-panel use.
Installation#
Usage#
The preview is yours to explore. Its code comes with a Pro license, paid once and used in every project.
Have a license? Unlock it here
Anatomy#
import {
EmptyState,
EmptyStateMedia,
EmptyStateTitle,
EmptyStateDescription,
EmptyStateActions,
} from "@/components/ui/empty-state"
<EmptyState>
<EmptyStateMedia />
<EmptyStateTitle />
<EmptyStateDescription />
<EmptyStateActions />
</EmptyState>Variants#
The variant prop colors the icon from a single semantic token. The tile around it stays neutral, with no fill and the plain border, so a search, error, or success state reads as one family across all four themes. Set it on the root and every part picks it up through context.
Illustrated states#
Give each empty moment a small object that belongs to the job: an archive waiting for its first project, a mail sorter with no letters, or a search bench with an empty tray. Keep the machine quiet and let the title and description explain what happened.
Density#
density retunes padding, the media and icon size, the title size, and the description measure, never color or the rounded brand corners. comfortable suits a full page or marketing surface; compact (the default) fits an in-panel placeholder. Without a prop it reads the nearest DensityProvider, so an app shell can set it once.
Without actions#
The action row is optional; drop EmptyStateActions for a purely informational placeholder.
Inline#
An empty list inside a record (no evidence, no linked vehicles) sits between sections that have content, and the stacked block would outweigh all of them. layout="inline" puts the same parts on one line: a small tile, the title as a muted message, and any action pushed to the end.
API reference#
EmptyState
The root: a centered column that shares variant and density with every part through context. Forwards all native <div> props; every part accepts className, merged last.
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "default" | "primary" | "success" | "warning" | "info" | "destructive" | "default" | Colors the media icon from one semantic token; the tile stays neutral in every variant. |
| density | "comfortable" | "compact" | "compact" | Retunes padding, the media and icon size, the title size and the description measure. Falls back to the nearest DensityProvider. |
| layout | "stacked" | "inline" | "stacked" | inline lays the parts on one left-aligned line (small tile, the title as a muted message, actions at the end) for an empty list inside a sheet or panel. Mirrored as data-layout. |
| asChild | boolean | false | Merge onto your own element via Radix Slot instead of rendering a <div>. |
EmptyStateMedia
The neutral icon tile (hairline ring, no fill), sized by density; wrap a single icon. Rendered aria-hidden, and forwards all native <div> props.
| Prop | Type | Default | Description |
|---|---|---|---|
| asChild | boolean | false | Merge onto your own element via Radix Slot instead of rendering a <div>. |
EmptyStateTitle
The balanced, semibold title. Renders a <div> and forwards all native <div> props.
EmptyStateDescription
Muted supporting copy kept to a readable measure. Forwards all native <p> props.
EmptyStateActions
The optional action row; holds one outline Button, since an empty state points at a single next step. Forwards all native <div> props.
| Prop | Type | Default | Description |
|---|---|---|---|
| size | "sm" | "md" | "lg" | "sm" | Control height imposed on the children, so the button needs no size; an explicit one still wins. |
| Data attribute | Description |
|---|---|
| data-control-size | The imposed control size. |