Feedback
Empty
A calm, centered placeholder for views with nothing to show yet, with an icon, a title, a description and actions.
npx prodular-ui add emptyFirst use
Explain what will appear here and offer the action that fills it.
No invoices yet
Invoices appear here once a customer is charged. Create one by hand or connect Stripe to import your history.
import { PlusIcon, ReceiptTextIcon } from "lucide-react"
import { Button } from "@/components/ui/button"import { Empty, EmptyActions, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle,} from "@/components/ui/empty"
export default function EmptyDefault() { return ( <Empty> <EmptyHeader> <EmptyMedia variant="icon"> <ReceiptTextIcon /> </EmptyMedia> <EmptyTitle>No invoices yet</EmptyTitle> <EmptyDescription> Invoices appear here once a customer is charged. Create one by hand or connect Stripe to import your history. </EmptyDescription> </EmptyHeader> <EmptyActions> <Button> <PlusIcon data-icon="inline-start" /> Create invoice </Button> <Button variant="outline">Import from Stripe</Button> </EmptyActions> </Empty> )}No results
Inside a card, after filtering. Offer a way back.
import { SearchIcon } from "lucide-react"
import { Button } from "@/components/ui/button"import { Card, CardContent, CardDescription, CardHeader, CardTitle,} from "@/components/ui/card"import { Empty, EmptyActions, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle,} from "@/components/ui/empty"
export default function EmptySearch() { return ( <Card className="w-full max-w-lg"> <CardHeader className="border-b"> <CardTitle>Customers</CardTitle> <CardDescription>Filtered by plan: Enterprise, region: APAC</CardDescription> </CardHeader> <CardContent> <Empty className="py-6"> <EmptyHeader> <EmptyMedia variant="icon"> <SearchIcon /> </EmptyMedia> <EmptyTitle>No customers match these filters</EmptyTitle> <EmptyDescription>Try a wider date range or remove a filter.</EmptyDescription> </EmptyHeader> <EmptyActions> <Button variant="outline" size="sm"> Clear filters </Button> </EmptyActions> </Empty> </CardContent> </Card> )}Anatomy
<Empty> <EmptyHeader> <EmptyMedia variant="icon"><ReceiptTextIcon /></EmptyMedia> <EmptyTitle>No invoices yet</EmptyTitle> <EmptyDescription>Invoices appear here once a customer is charged.</EmptyDescription> </EmptyHeader> <EmptyActions> <Button>Create invoice</Button> </EmptyActions></Empty>Guidance
Use it when
- A list, table or view that has no data yet, or no results for the current filters.
- First run states where the next step is clear.
Avoid
- Errors. Use an Alert that says what failed and how to retry.
- Illustrations or emoji. One muted icon is enough.
- More than two actions.
Rules for AI agents
Published in llms-full.txt and the registry, so coding agents follow them when they build with this component.
- Write EmptyTitle as a plain statement: No invoices yet, No customers match these filters.
- Use EmptyDescription to say what will appear here and how to make it appear, in one or two sentences.
- Put buttons in EmptyActions, primary first. For no results states use a single outline Clear filters button.
- Use EmptyMedia variant="icon" with a lucide icon that names the content type.
- Inside a card, place Empty in CardContent and reduce padding with className="py-6". Do not add a border.
API
EmptyMedia
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "default" | "icon" | "default" | icon puts a lucide icon on a muted tile. |
EmptyActions
| Prop | Type | Default | Description |
|---|---|---|---|
| children | ReactNode | A centered row of buttons. |
EmptyContent
| Prop | Type | Default | Description |
|---|---|---|---|
| children | ReactNode | Free form content under the header, such as a search field or a link. |