Search docs

Jump to any table example

Discord—

Shadcn Empty State Table

Two different empty tables, handled separately: one with no data yet (with a call to action) and one where a search matches nothing (with a way to clear it).

$ npx shadcn add https://www.shad-table.dev/r/empty-state-table.json
CustomerStatus
Amount
Due

No invoices yet

Invoices you create will show up here so you can track what's paid and what's overdue.

How it works

1."No data" and "no results" are different problems

An empty list needs the user to create something; an empty search needs them to change the search. The table tells them apart by checking the source data length, not the filtered row count, and shows a different icon, message, and action for each.

src/components/empty-state/data-table.tsx
const hasNoData = data.length === 0 // source is empty
const rows = table.getRowModel().rows // filtered result
{hasNoData ? <EmptyState title="No invoices yet" ... /> : <EmptyState title="No results found" ... />}

2.The empty state lives inside the table body

It renders in a single row with colSpan equal to the column count, so the header stays in place and the table keeps its borders and width. Collapsing to a standalone card makes the layout jump when data arrives.

src/components/empty-state/data-table.tsx
<TableRow className="hover:bg-transparent">
<TableCell colSpan={columns.length} className="p-0">
{emptyState}
</TableCell>
</TableRow>

3.Every empty state has a next step

EmptyState takes an optional action slot. First-use passes a Create button; no-results passes a Clear search button that resets the global filter. An empty state without an action is a dead end.

src/components/empty-state/empty-state.tsx
interface EmptyStateProps {
icon: React.ReactNode
title: string
description: string
action?: React.ReactNode
}

4.The search input is disabled when there is nothing to search

With no data, filtering can't produce anything, so the input is disabled rather than inviting a search that can only lead to a misleading "no results" message.

src/components/empty-state/data-table.tsx
<Input
placeholder="Search invoices..."
disabled={hasNoData}
/>