Empty State
betaWhat a list, table, or page shows when it has nothing in it yet: an icon, a title, a short description, and one or two actions.
Built from Button.
Preview
No projects yet
Projects keep your tasks, files, and people in one place. Create one to get started, or bring yours over from another app.
no results, size sm, inside a card
Invoices
No invoices match
Nothing was sent to this customer in March.
error, tone danger
Could not load invoices
Check your connection, then try again. Your invoices are safe.
no icon, no actions
Nothing to review
When someone asks for your review, it shows up here.
size lg, for a whole page
Your inbox is empty
Messages from your team and your customers land here.
narrow container
No projects yet
Create one to get started.
Install
1. Add the registry to
components.json, once per app. Without it, the shadcn CLI looks up@txbrendanin a public list that txbrendan/ui does not control.npx shadcn@latest registry add "@txbrendan=https://txbrendan.dev/r/{name}.json"2. Add the theme, once per app. It replaces your color tokens with ones checked for contrast.
npx shadcn@latest add @txbrendan/theme3. Add the block. It also adds every component it uses. Its own files go in your
componentsfolder, and they are yours to edit.npx shadcn@latest add @txbrendan/empty-state
Use it for
- A list, table, or page that has nothing in it yet. Say what will show up here and how to add the first one.
- A search or filter that found nothing. Say so, and offer a way to clear the filter.
- A section that failed to load. Set tone="danger" and offer a Retry button.
- Pass one or two Buttons in actions, the main one first. With size="sm", pass size="sm" Buttons too.
- Make every action an emphasis="ghost" Button, so the next step stays quiet. With two actions, give the main one tone="brand" so it stands apart.
- Write the title so it makes sense without the icon, since screen readers skip the icon.
Avoid it for
- Content that is still loading. Show a skeleton, then the empty state once you know there is nothing.
- A setup checklist for someone's first visit. Use First Use instead.
- A message about the whole app, like an outage or a billing problem. Use Alert.
- More than two actions. Pick the one that matters, and link to the rest from the description.
Props
- title
What is missing, in a few words, like "No projects yet". Required.
ReactNode
- description
One or two short sentences: what will show up here, and how to start.
ReactNode
- icon
An icon element, like <FolderIcon />. It sits in a round tile above the title.
ReactNode
- actions
One or two Buttons or links. Put the main one first. Below 18rem wide they stack.
ReactNode
- tone
Color of the icon tile. Use "danger" when something failed to load.
"neutral" | "brand" | "danger" | "success" | "warning" · default "neutral"
- size
sm inside a list or card, md for a section, lg for a whole page. Scales the space, icon, and text.
"sm" | "md" | "lg" · default "md"
- headingLevel
The title's heading level, so it fits under the heading above it.
1 | 2 | 3 | 4 | 5 | 6 · default 2
- className
Extra classes on the outer div, which holds the container query. Add a border here to frame it.
string
| Prop | Type | Default | What it does |
|---|---|---|---|
| title | ReactNode | - | What is missing, in a few words, like "No projects yet". Required. |
| description | ReactNode | - | One or two short sentences: what will show up here, and how to start. |
| icon | ReactNode | - | An icon element, like <FolderIcon />. It sits in a round tile above the title. |
| actions | ReactNode | - | One or two Buttons or links. Put the main one first. Below 18rem wide they stack. |
| tone | "neutral" | "brand" | "danger" | "success" | "warning" | "neutral" | Color of the icon tile. Use "danger" when something failed to load. |
| size | "sm" | "md" | "lg" | "md" | sm inside a list or card, md for a section, lg for a whole page. Scales the space, icon, and text. |
| headingLevel | 1 | 2 | 3 | 4 | 5 | 6 | 2 | The title's heading level, so it fits under the heading above it. |
| className | string | - | Extra classes on the outer div, which holds the container query. Add a border here to frame it. |
Accessibility
- The title is a real heading, an h2 by default. Set headingLevel to one below the heading the empty state sits under.
- The icon tile is hidden from screen readers, so the title has to say what is missing on its own.
- The block adds nothing that takes focus. Only the actions you pass are in the tab order, in the order you pass them.
- Other props, like role or aria-label, go on the outer div.
Examples
Nothing here yet
<EmptyState
icon={<FolderPlus />}
title="No projects yet"
description="Projects keep your tasks, files, and people in one place."
actions={
<>
<Button tone="brand" emphasis="ghost">New project</Button>
<Button emphasis="ghost">Import</Button>
</>
}
/>A search with no results
<EmptyState
size="sm"
headingLevel={3}
icon={<SearchX />}
title="No matches"
description="Nothing matches those filters."
actions={<Button size="sm" emphasis="ghost">Clear filters</Button>}
/>Failed to load
<EmptyState
tone="danger"
icon={<CircleAlert />}
title="Could not load invoices"
description="Check your connection, then try again."
actions={<Button emphasis="ghost">Try again</Button>}
/>