Empty state
An icon, one line and one action for a list with nothing in it yet.
npx shadcn@latest add https://ui.goodtabs.co/r/empty-state.json
With the @goodtabs namespace in components.json: npx shadcn@latest add @goodtabs/empty-state
No saved tabs yet.
Readable at 250px.
No results
Nothing matches that filter.
Boxed, with a secondary action.
Text only
No activity this week.
A dashed box and one line.
Usage
import { EmptyState } from "@/components/ui/empty-state"
<EmptyState title="No saved tabs yet." />Props
| Prop | Type | Default | Description |
|---|---|---|---|
| icon | ReactNode | An icon drawn in a quiet tile. | |
| title | string | One line saying what is missing. | |
| action | ReactNode | The one action, usually a Button. |
Source
empty-state/empty-state.tsx
import * as React from "react";
import { cn } from "@/lib/utils";
type EmptyStateProps = Omit<React.ComponentProps<"div">, "title"> & {
/** An icon, drawn in a quiet tile. Decorative. */
icon?: React.ReactNode;
/** One line saying what is missing and why. */
title: string;
/** The one action, usually a Button. */
action?: React.ReactNode;
};
/** Icon, one line and one action, for a list or page with nothing in it yet. */
export function EmptyState({ icon, title, action, className, ...props }: EmptyStateProps) {
return (
<div className={cn("flex flex-col items-center gap-3 text-center", className)} {...props}>
{icon && (
<span
aria-hidden="true"
className="inline-grid size-9 place-items-center rounded-lg bg-muted text-foreground [&_svg]:size-4"
>
{icon}
</span>
)}
<p className="m-0 text-sm text-muted-foreground">{title}</p>
{action}
</div>
);
}
For AI agents
Hand your agent this page, the markdown at /components/empty-state/prompt.md, or the Copy AI prompt button above.
When to use
- Lists, tables and pages before the first item exists
- Search or filters that match nothing
When not to use
- Errors: say what failed and how to retry
- Loading: use a skeleton or spinner
Agent notes
- Keep the line to one sentence and make the action the way out
- The icon is decorative and aria-hidden
- Pass a Button as action; it is not built in