Skip to content
EspañolEnglish
All components (204)

Empty state

Surfaces · EmptyState · .amset-empty

What it is and when to use it

The gap when there is nothing to show. It never stops at "No data": it says why it is empty and what can be done, because an empty state with no way out looks like a broken screen.

When to use it

  • A list, a table or a panel that has nothing yet, with the action that creates the first item.
  • The response to a search or a filter with no results: with announce, so it is read when it appears, and an action to clear the filters.
  • size: sm (and withoutIcon) for small gaps inside a card, lg when the empty state fills the screen.
  • align="start" in a side panel or a column, where centered text looks loose.
  • tone colors the icon circle: neutral by default, because an empty state is not an alarm. icon changes the drawing.

When not to

  • What is left after an action (payment made, payment declined, 404): Result.
  • While loading: Skeleton. An empty state that appears too early says there is nothing when there is.
  • A problem inside a screen that keeps working: Alert.

Keyboard: the gap is not focusable; the action and secondary buttons have their own Tab stop.

Accessibility: the title is a real heading, h3 by default (headingLevel adjusts it to the place where it goes). The icon is decorative. With announce the block is role="status" and is read when it appears; without it, it is not announced, because a gap that has always been there is not news.

Fine-tuning: CSS variables --amset-empty-*: -padding-block, -padding-line, -slot, -icon (the side of the circle), -icon-drawing, -title, -font and -width (the maximum width of the description: 38ch, 44ch in lg). It appears with a short fade, which is removed with reduced motion.

What it looks like

No orders match those filters

Try removing the date range or searching by another status.

<EmptyState
  title="No orders match those filters"
  description="Try removing the date range or searching by another status."
  action={<Button variant="outline">Clear filters</Button>}
/>

Props

Import it with import { EmptyState } from '@amset/ui'. Required props are marked.

PropTypeWhat it does
titlerequiredstring—
actionReactNodeMain button: create the first item, clear the filters.
alignEmptyStateAlignment`start` for a side panel or a column, where centered text looks loose.
announcebooleanAnnounces it on appearing. For when the empty state is the answer to something the person has done (searching, filtering): otherwise the result of their search happens in silence.
classNamestringMerged with the library classes; it does not replace them.
descriptionReactNode—
headingLevelEmptyStateHeadingLevel—
iconReactNodeOwn icon. Decorative: what counts is the title.
secondaryReactNode—
size"sm" | "md" | "lg"`sm` inside a card or a row; `lg` when it takes up the screen.
tone"neutral" | "accent" | "secondary" | "tertiary" | "info" | "success" | "warning" | "error"Color of the icon's circle. `neutral` by default: an empty state is not an alarm.
withoutIconbooleanNo icon, for small gaps inside a card.

It also accepts the attributes of the element it renders: className, style, data-*, aria-* and its events.

CSS variables

These CSS variables are how you adapt it. Declare them on the component's selector, not on :root: the stylesheet redeclares them in the rule itself, and a declaration on the same element always wins.

VariableDefault
--amset-empty-padding-blockvar(--amset-space-8)
--amset-empty-padding-linevar(--amset-space-5)
--amset-empty-slotvar(--amset-space-2)
--amset-empty-icon3rem
--amset-empty-icon-drawing1.5rem
--amset-empty-titlevar(--amset-text-lg)
--amset-empty-fontvar(--amset-text-base)
--amset-empty-width38ch
--amset-empty-icon-backgroundvar(--amset-divider)
--amset-empty-icon-inkvar(--amset-ink-2)

How to change it

.amset-empty {
  --amset-empty-padding-block: ...;
  --amset-empty-padding-line: ...;
}

In the test bench

Every state and variant, to try one at a time, on its page at ui.amset.tech: