Components · Status and feedback
EmptyState
What will appear here, and the action that creates it.
First run
No tickets yet
New tickets from your inbox and portal appear here.
Press N to create a ticket from anywhere.
import { Button, EmptyState, Kbd } from '@rookcom/monarch-react';
// PlusIcon: demo icon from the docs site; use your own.
<EmptyState
icon={<PlusIcon />}
title="No tickets yet"
description="New tickets from your inbox and portal appear here."
actions={
<>
<Button variant="primary">New ticket</Button>
<Button>Import</Button>
</>
}
tip={
<>
Press <Kbd>N</Kbd> to create a ticket from anywhere.
</>
}
/>Usage examples
Filtered and all clear
import { EmptyState } from '@rookcom/monarch-react';
<EmptyState
kind="filtered"
size="compact"
title="No results match these filters"
description="Try a different search or clear the filters."
onClearFilters={() => {}}
/>
<EmptyState
kind="success"
size="compact"
title="You're all caught up"
description="New items will appear here."
/>One line
import { Button, EmptyState } from '@rookcom/monarch-react';
// ListIcon: demo icon from the docs site; use your own.
<EmptyState
layout="line"
icon={<ListIcon />}
headingLevel="p"
title="No activity this week"
description="Changes to records show up here."
actions={<Button size="sm">View all activity</Button>}
/>Purpose
Shown when there is nothing to display: says what will appear and offers the action that creates it, or a way back when a filter matched nothing.
Use when
- A list, table or view has no items yet (
kind="first-run", the default). - A search or filter returns nothing (
kind="filtered"withonClearFilters). - A queue is empty because the work is done (
kind="success"). - A dashboard section or table body is empty and needs a one-line note (
layout="line",size="compact").
Avoid when
- Loading failed: use ErrorState or InlineErrorRetry.
- Content is still loading: use LoadingState.
- A whole route is missing or forbidden: use ErrorPage.
Design principles
- Say what will appear here, then offer the action that creates it. The product writes every word; the component only lays it out.
- First-run and filtered states read differently: first-run explains and invites, filtered offers a way back (Clear filters) rather than a create action.
- The heading level is configurable so the state fits the page outline;
pavoids a heading inside a table cell. - One accent-tinted icon tile at most;
successswitches it to the success tint. The rest stays neutral.
API reference
import { EmptyState } from '@rookcom/monarch-react';| Export | Kind | Rendering | Root class |
|---|---|---|---|
EmptyState | component | server-safe | .mn-empty-state |
All native <div> attributes pass through, and the ref is forwarded to the root <div>.
children render after the actions (for example a short list of next steps); tip renders last in small muted text.
Generated from the TypeScript declarations of packages/react/src/components/feedback/empty-state.
Properties
EmptyState
Shown when there is nothing to display yet. Say what will appear here and offer the action that creates it.
| Prop | Type | Description |
|---|---|---|
title required | ReactNode | |
actions | ReactNode | Primary and secondary actions, usually Buttons. |
children | ReactNode | Extra content after the actions, such as a list of next steps. |
className | string | |
clearFiltersLabel | string | Label of the clear-filters button. Default "Clear filters". |
description | ReactNode | |
headingLevel | EmptyStateHeadingLevel | Title element. Default `h3`. Match the page outline (no skipped levels); use `p` where a heading would be wrong, such as inside a table cell. |
icon | ReactNode | Decorative icon in a tinted tile. Hidden from assistive technology. |
id | string | |
kind | EmptyStateKind | Why the view is empty. Exposed as `data-kind`. Default `first-run`. |
layout | "stack" | "line" | `stack` (default) centres icon, text and actions in a column; `line` is a single left-aligned row (icon, text, actions) for a list or dashboard section that has nothing in it. |
onClearFilters | (() => void) | With `kind="filtered"`, renders a "Clear filters" button before any other actions. The product resets its own filters. |
size | "inline" | "page" | "compact" | `inline` (default) sits inside a card or table; `page` fills an empty view; `compact` is a tighter block for table bodies, side panels and small cards. |
tip | ReactNode | A short hint under the actions, such as a keyboard shortcut (compose it with Kbd). Shown in small muted text. |
Variants
| Prop | Values | Description |
|---|---|---|
size | 'inline''page''compact' | inline (default) sits inside a card or table; page adds vertical padding to fill a view; compact tightens padding, icon and title for table bodies and side panels. Exposed as data-size. |
layout | 'stack''line' | stack (default) centres everything in a column; line is one left-aligned row of icon, text and actions. line is exposed as data-layout="line". |
kind | 'first-run''filtered''success' | filtered adds a Clear filters button when onClearFilters is set; success uses the success tint and a check icon when no icon is given. Non-default kinds are exposed as data-kind. |
headingLevel | 'h1''h2''h3''h4''h5''h6''p' | Title element. Default h3. |
States
| State | Exposed as | Behaviour |
|---|---|---|
| First run | – | The default: icon, title, description and actions. |
| Filtered | data-kind="filtered" | Clear filters (secondary button, label clearFiltersLabel) is rendered before the other actions. |
| Success | data-kind="success" | Success-tinted icon tile; a check icon when no icon is passed. |
Interaction behaviour
- Clear filters calls
onClearFilters; the product resets its own filters and the list re-renders. - Other actions keep their own behaviour.
Keyboard support
| Keys | Action |
|---|---|
| Tab / Shift+Tab | Moves through Clear filters and the actions, in that order. |
| Enter / Space | Activates the focused action. |
The empty state itself is not focusable.
Accessibility
- Role
- none; the title is a heading (or a paragraph with
headingLevel="p") - Accessible name
- –
- The icon tile is
aria-hidden; meaning is carried by the title. - The title is a real heading (h3 by default); pick the level that continues the page outline instead of skipping levels.
- No live region: an empty state is page content, not an announcement. When it replaces results after a filter change, the product announces the result count itself.
- Verified with axe in jsdom (each kind and layout) and in Chromium, Firefox and WebKit on /components/empty-state.
Responsive behaviour
stackis centred with a 28rem maximum width; text wraps at narrow widths and actions wrap onto new lines.linewraps: the text takes the remaining width (12rem minimum) and the actions drop below it at 320px.
Theme support
- The icon tile uses the accent subtle and strong tokens, so it follows the product accent;
successuses the success tokens. - Colours are Monarch semantic tokens only, so light, dark and more-contrast themes apply automatically.
Do and don't
Do
- Describe what will appear, not that nothing is there.
- Offer at most one primary action.
- Use
kind="filtered"when a filter is active, so the way out is Clear filters, not Create. - Keep next-step logic (which action to suggest) in the product and pass the result as
actions.
Don't
- Do not use an empty state to report an error.
- Do not reuse the first-run copy for a filtered result: "No tickets yet" is wrong when tickets exist but are filtered out.
Related components
- ErrorState: Something failed to load.
- LoadingState: Content is on its way.
- InlineErrorRetry: One section failed and can be retried in place.
- ErrorPage: A whole route is missing, forbidden or down.
Dependencies
| Kind | Depends on |
|---|---|
| npm packages | react |
| Monarch components | Button |
Testing coverage
- Renders the title as an h3 by default;
headingLevelchanges it,prenders no heading. - Default props keep the 0.3 markup (no
data-kindordata-layout; decorative icon). - Filtered renders Clear filters first and activates it from the keyboard; other kinds never render it.
- Success shows a check icon unless one is passed;
lineandcompactare exposed as data attributes. - Tip and children render after the actions; the ref is forwarded.
| Check | Covered |
|---|---|
| Axe in jsdom | Yes |
| Server rendering | Yes |
| Browser suites | Visual baselines: /__gallery; Cross-browser axe: /components/empty-state |
Tests: packages/react/src/components/feedback/empty-state