Empty
A centered empty-state layout for when there’s nothing to show — a list with no rows, a search with no matches, or a screen the user has fully cleared. Reach for it instead of leaving a blank panel: a glyph, a one-line title, and a sentence of guidance turn dead space into a next step.
Compose the parts: Empty (the centered, dashed-border container), EmptyHeader (groups the media + text, capped at max-w-sm), EmptyMedia (the icon tile), EmptyTitle, EmptyDescription, and EmptyContent (where actions live). Every part is a vertical Stack under the hood, so gap, align, and justify are props — no className wrestling.
Basic
The full pattern: an icon media tile, a title, a description, and a call-to-action in EmptyContent. This is the “no shipments yet” first-run screen.
Without an action
Drop EmptyContent when there’s nothing for the user to do — an error or informational state. Just the EmptyHeader (media + title + description) stands on its own.
No results
A search or filter that returned nothing. EmptyMedia variant="icon-muted" reads quieter than a first-run prompt, and the action resets the query rather than starting something new.
Resolved state
EmptyMedia variant="icon-success" tints the tile green for an “all caught up” outcome — a queue the user has emptied on purpose, not a screen that’s empty because nothing exists yet.
Media variants
EmptyMedia ships four variants. default is a bare, unstyled wrapper; the three icon-* variants render a 48px tile that auto-sizes an unsized leading svg. Pick by tone: icon for neutral, icon-muted for low-emphasis (no-results), icon-success for resolved.
Reference
Empty
The centered container. Extends VStack props (minus direction); defaults to gap={4}, centered on both axes, with a dashed border, p-12, and balanced center text.
| Prop | Type | Default | Description |
|---|---|---|---|
gap | number | 4 | Vertical gap between children |
align | "start" | "center" | "end" | "stretch" | "center" | Cross-axis alignment |
justify | "start" | "center" | "end" | "between" | "center" | Main-axis alignment |
className | string | — | Merged onto the container |
EmptyHeader
Groups the media, title, and description. Extends VStack props (minus direction); capped at max-w-sm, gap={2}, centered.
| Prop | Type | Default | Description |
|---|---|---|---|
gap | number | 2 | Vertical gap between children |
align | string | "center" | Cross-axis alignment |
className | string | — | Merged onto the header |
EmptyMedia
The icon tile. Extends <div> props.
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "default" | "icon" | "icon-muted" | "icon-success" | "default" | default is an unstyled wrapper; icon-* render a 48px tile and auto-size an unsized leading svg |
className | string | — | Merged onto the tile |
EmptyTitle
The heading line (text-lg font-medium). Extends <div> props.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | Merged onto the title |
EmptyDescription
The supporting copy (text-sm muted). Nested <a> elements get underline + hover styling for free. Extends <p> props.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | Merged onto the description |
EmptyContent
Holds the action(s) below the header. Extends VStack props (minus direction); gap={4}, centered, capped at max-w-sm. Wrap multiple buttons in an HStack to lay them out in a row.
| Prop | Type | Default | Description |
|---|---|---|---|
gap | number | 4 | Vertical gap between children |
align | string | "center" | Cross-axis alignment |
className | string | — | Merged onto the content |