EmptyState
import { EmptyState } from 'tenet-ui';Also accepts every prop of Omit<HTMLAttributes<HTMLDivElement>, 'title'>.
Source: src/components/EmptyState/EmptyState.tsx
Usage guidelines
Section titled “Usage guidelines”When to use: a table, list, inbox, search or filter that has nothing to show — first run (“No stories yet”), an exhausted filter (“No results for ‘budget’”), a cleared queue (“You’re all caught up”). For zero records, render it in place of the rows, inside the same Card/Table.Container, so the layout doesn’t jump. For an exhausted search or filter, keep the table and its toolbar on screen and pass a compact EmptyState (headingLevel={4}, no size="large") as DataTable emptyText. It is not for errors (use Banner variant="danger") or for loading (use Skeleton/Spinner).
titleis required and specific: name what is empty and, for filters, echo the query. Avoid “Nothing here” / “Oops”.descriptionexplains why and what to do next in one or two sentences; keep it inline content (it renders inside a paragraph).actionis the single step that fixes the emptiness — aButton variant="primary"(“Create story”, “Clear filters”).secondaryActionis optional and quieter (Button variant="invisible", aLinkto docs). Never two primaries; no action at all is fine when there is nothing the user can do.iconis decorative and is wrappedaria-hidden— the title already carries the meaning. Pass anIconor an inline<svg>that usescurrentColor; it is tintedfgColor-mutedand sized from the size scale. Don’t put text or a status meaning in it.headingLevel(2–4, default 3) sets the title’s rank in the outline so it nests under the surrounding page/section heading; its visual size followssize. Usesize="large"only for whole-page or first-run states.- Don’t hand-build one: a centered
<div>with inlinetextAlignand a<h3 style>skips the type scale, the muted tone and the outline rules this component encodes.
Do / Don’t
Section titled “Do / Don’t”- ✅
<EmptyState title="No stories yet" description="Stories you create or are assigned will appear here." action={<Button variant="primary">Create story</Button>} /> - ✅
<EmptyState title={No results for “${query}”} description="Try a different spelling or clear the filters." action={<Button onClick={clear}>Clear filters</Button>} headingLevel={4} />passed asDataTableemptyText, so the toolbar and active filters stay. - ✅
<EmptyState size="large" headingLevel={2} icon={<InboxIcon />} title="You're all caught up" />as a page’s only content under itsh1. - ❌
<div style={{ textAlign: 'center', padding: 40 }}><h3>Nothing here</h3></div>— off-system and unspecific. - ❌
<EmptyState title="Error" description="Request failed" />— failures are aBanner, not an empty state.
See also: DataTable (emptyText for an exhausted filter), Banner for failures, Skeleton while loading; system guidelines data-display (when a collection shows an EmptyState) and content (title, description, and action copy).
Examples
Section titled “Examples”6 stories for EmptyState — open in Storybook
- Default
components-emptystate--default - Title Only
components-emptystate--title-only - With Icon
components-emptystate--with-icon - With Actions
components-emptystate--with-actions - Large
components-emptystate--large - Search Results
components-emptystate--search-results
The full matrix (all args, controls, accessibility panel) is in Storybook.
| Prop | Type | Default | Description |
|---|---|---|---|
title * | string | — | Short, specific headline — say what is empty ("No stories yet"), not just "Nothing here". |
description | ReactNode | — | One or two sentences: why it is empty and what to do next. Inline content (rendered in a muted Text). |
icon | ReactNode | — | Decorative illustration or icon; wrapped aria-hidden — the title carries the meaning. |
action | ReactNode | — | The primary next step, usually a Button variant="primary". |
secondaryAction | ReactNode | — | An optional secondary step next to action (a default/invisible Button or a Link). |
size | 'medium' | 'large'EmptyStateSize | medium | Overall scale: medium for a region inside a page, large for a whole-page/first-run state. |
headingLevel | 2 | 3 | 4EmptyStateHeadingLevel | 3 | Semantic heading rank of the title (h2/h3/h4) so it fits the surrounding outline. The visual size follows size, not this prop. |
* required