Empty
The block a list shows when it has nothing in it.
No studies match these filters
Nothing in the last 24 hours is both CT Head and marked urgent. Widen the date range, or clear the modality filter.
Installation
npx shadcn@latest add https://qure-ui.qure.ai/r/empty.jsonUsage
import {
Empty, EmptyActions, EmptyDescription, EmptyMedia, EmptyTitle,
} from '@/components/ui/empty'<Empty>
<EmptyMedia>
<FilterXIcon />
</EmptyMedia>
<EmptyTitle>No studies match these filters</EmptyTitle>
<EmptyDescription>Widen the date range, or clear the modality filter.</EmptyDescription>
<EmptyActions>
<Button variant="secondary">Clear filters</Button>
</EmptyActions>
</Empty>There is no Base UI primitive here and nothing to borrow — an empty state has no behaviour. What it has is a shape people recognise, and the discipline to keep the last part of that shape present: nothing found with no way out is a dead end.
Composition
<Empty> {/* the block; owns size and variant */}
<EmptyMedia> {/* the icon, aria-hidden */}
<EmptyTitle> {/* what happened, in one line */}
<EmptyDescription> {/* why, and what would change it */}
<EmptyActions> {/* the way out — one primary action, at most one beside it */}
</Empty>EmptyActions is the part worth arguing about. Every other slot describes the situation; only
this one resolves it. If you cannot think of an action, that is usually a sign the description is
wrong rather than a sign the state has no exit — "no results for ACC-447190" can offer a
different way to search even when it cannot offer results.
EmptyMedia is aria-hidden. A screen reader announcing "image, magnifying glass" before
"No studies match these filters" adds nothing the title does not already say.
Nothing found
No results for “ACC-447190”
Accession numbers on this site are ten digits. Check for a missing digit, or press ⌘K to search by patient name instead.
Quote the query back. Without it the reader cannot tell a typo from a genuinely empty result, and the two need completely different responses. Here the way out is the shortcut they will reach for next rather than a button — see Kbd.
Nothing yet
Your worklist is empty
Studies appear here as the PACS routes them to you. Nothing has arrived since your shift began at 08:00.
A different state, and it should read differently. There is no filter to clear and no query to fix, so the description explains the mechanism — how studies get here — and the single action starts the work.
Distinguishing the two matters more than it looks. A first-run screen that says "no results" implies the reader did something wrong.
In a panel
No prior imaging
Nothing for this patient in the last 5 years at this site.
size="sm" with variant="bare" media, for a sidebar next to the images where the full block
would dominate. The heading is rendered as an h4 so it sits beneath the card's own title:
<EmptyTitle render={<h4 />}>No prior imaging</EmptyTitle>EmptyTitle defaults to <h3> because an empty state is usually the only content of its region.
Inside something that already has a heading, push it down a level rather than leaving a gap in the
document outline.
A region to be filled
Drop a DICOM study here
A folder of .dcm files, or a DICOMDIR. Studies are de-identified on upload.
The dashed outline says this holds something. Use it for a drop target.
Do not use variant="outline" for a list that happens to be empty. The border implies a place
to drop or click, and a border that promises an interaction which is not there is worse than no
border.
API Reference
Empty
| Prop | Type | Default | Description |
|---|---|---|---|
size | "sm" | "md" | "md" | sm inside a panel or a table body; md for a whole page. |
variant | "plain" | "outline" | "plain" | outline draws the dashed border. |
EmptyMedia
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "tile" | "bare" | "tile" | tile puts the icon in a tinted round tile; bare draws it alone. |
EmptyTitle
| Prop | Type | Default | Description |
|---|---|---|---|
render | ReactElement | <h3 /> | Change the heading level to fit the surrounding outline. |
EmptyDescription renders a <p> and EmptyActions a <div>; both take the usual props for
those elements.