Empty states
What to show when there is nothing to show, and how to write it so the user knows what to do next.
An empty state appears whenever a list, table, chart or panel has no content. It is a moment to explain, not a dead end: the user should always learn why the area is empty and what they can do about it.
Kinds of empty state
These look alike and are not. Each needs its own message, and often its own component.
| Kind | When | Tell the user | Component |
|---|---|---|---|
| Nothing yet | First use: no data has arrived or been created | What will appear here, and how to get it there | List Empty State with an action |
| No results | A search or filter matched nothing | That the filters caused it, and how to widen them | List Empty State with Clear filters |
| All done | The user cleared a queue | That the work is finished | List Empty State, no action |
| Failed to load | The request failed | That something went wrong and that they can try again | List Error State |
| No permission | The user lacks the permission for this area | That access is restricted and who can grant it | The app’s access-denied state on List Empty State |
| Not contracted | The tenant does not have the module | That the module is not part of their plan | The app’s module-unavailable state on List Empty State |
The last three are not “no data”: showing “No alerts yet” for a failed request or a missing permission tells the user something false.
No alerts yet
Alerts appear here as soon as a connector reports a detection.
<ListEmptyState
title="No alerts yet"
description="Alerts appear here as soon as a connector reports a detection."
/>Writing
- Title: why the area is empty, in one short line, without a period. “No alerts yet”, “No assets match these filters”.
- Description: what happens next or what to do, in one to three full sentences, with periods. “New alerts appear here as soon as a detection rule matches.”
- Name the object (“alerts”, “assets”), not “items”, “data” or “results” when you can.
- Keep it neutral. An empty state is not an error and not a celebration.
Actions
- Offer an action when there is one clear next step: create the first rule, clear the filters, try again.
- Use an
outlinebutton or a link, never thedefault(primary) variant: the empty state is not the main task of the page. - Show the action only if the user has the permission for it. Otherwise explain who can.
- One action. Two at most when they are true alternatives (Create rule, Import rules).
No alerts match these filters
Try a wider time range or remove a filter.
<ListEmptyState
icon={SearchXIcon}
title="No alerts match these filters"
description="Try a wider time range or remove a filter."
action={
<Button variant="outline" size="sm">
<FilterXIcon data-icon="inline-start" />
Clear filters
</Button>
}
/>Errors
A failed request uses List Error State: it says the data could not be loaded and offers Try again. Never put the raw error message in it; log it instead.
Something went wrong
The data could not be loaded. Try again in a moment.
function ListErrorStateDemo() {
return <ListErrorState onRetry={() => {}} />
}Size and repetition
- In small containers (a card, a sidebar panel), drop the icon and keep only the text.
- When several areas of one screen are empty for the same reason (a new tenant, a filter that matches nothing), show one message for the screen instead of one per card.
- Keep the table header visible above an empty table, so the user still sees what the table would contain.