Skip to main content

What it is

An empty state fills a region that has nothing in it with an illustration, a short title, and an optional line of supporting text. It replaces the content, not the page: the header, controls, and footer stay where they are. Its name understates its range. The same component carries no data yet, no results, a failed load, and a completed milestone — the published examples include an error message and a congratulations message, and the illustration set includes one for each. What it is really for is any moment where a region has no content and the reader needs to know why.

Live example

Exports

Vocabulary

“Zero state” and “no results” are different messages, and this is the distinction that matters most. A zero state means the reader has not created anything yet, and the next step is to create one. No results means the data exists but the current filter or query excludes it, and the next step is to widen it. Telling a new user “no results” reads as a broken product; telling a searching user “get started” reads as a lost query. Product code has already discovered the distinction — the adoption data below includes separately named components for no models, no search results for models, and no archived models in the same application.

Choose EmptyState when

  • A region that normally holds content has none, and the reader needs to know why.
  • The reason is worth an illustration — the region is large enough that a bare line of text would read as a rendering failure.
  • There is something the reader can do about it, or a reason they can understand.

Choose something else when

Anatomy

There is no action slot, in code or in the design library. Both define an empty state as illustration plus title plus supporting line, and nothing else. An empty state that offers a way out — “Create your first campaign” — is built by placing a Button after the component, inside the same region.This matters because rules elsewhere require that action: TITAN-TBL-04 says an empty table offers the action that resolves it. That rule is satisfied by composition, not by the component.

Variants, sizes, and states

Fifteen illustrations ship, and the choice is the component’s only real variant axis: Pick by meaning, not by decoration. search says “your query matched nothing”; error says “this failed”. Reaching for airBalloon because it is the nicest drawing costs the reader the one piece of information the illustration was carrying. One size. The illustration is fixed at the empty-state-illustration-* dimensions and the component centres itself in whatever region contains it. There is no compact variant. A custom illustration bypasses the sizing. customIllustration is rendered as given, outside the wrapper that applies the size tokens — a published example passes an icon, which renders at icon size. If you pass your own, size it yourself to match.

Edge and failure states

Tokens

Two component tokens: empty-state-illustration-width and empty-state-illustration-height. The gap between the illustration and the text comes from spacing-5, and both lines of text come from the type scale.

Composition

An empty state replaces the content of a region, not the region. In a list view it goes inside Contents; the page header, its controls, and its footer stay. A reader whose filter matched nothing still needs the filter, in order to change it. The resolving action goes after it, in the same region. One action, and it is the one that fixes the state — create the first record, clear the filter, retry the load. A table’s empty state replaces the rows, not the table. Keep the column headers: they tell the reader what they would have been looking at, and they are what makes an empty table legible as a table.

Content

  • The title says what is not here, in the reader’s words: “No campaigns yet”. Not “Empty”, not “No data”.
  • The supporting line says what to do about it, in one sentence: “Create a campaign to start routing calls.”
  • Sentence case, no exclamation marks — see Capitalization.
  • Never say “records” in interface copy. A reader sees campaigns, calls, or rows.
  • Distinguish the two cases in the words, not only the illustration: “No campaigns yet” for a zero state, “No campaigns match these filters” for no results.
  • The action, if there is one, is a link button — never a solid one. Confirmed from source; see TITAN-EMPTYCOPY-04. Added this pass — this page didn’t previously state it.
The default message (“No Records found!”) breaks these rules — see Open issues. Do not rely on the fallback; always pass a title.

Accessibility

The title carries the region’s message, so it must be text — not baked into the illustration. An illustration with the message drawn into it is invisible to a screen reader. The illustration is decorative. It repeats what the title says, so it needs no description of its own; what it must not do is carry information the text omits. An empty state that appears in response to an action should be announced. A reader who applies a filter and gets no results needs to know that, and nothing about this component announces itself — the announcement belongs to the region that swapped its content. The supporting line renders as a heading, and it is not one (known issue) — title renders as an h3 and subTitle as an h6, which corrupts the heading outline of any page carrying an empty state.

Constraints

Known issues

EmptyState: open issues

Divergences, open decisions, and undocumented gaps for EmptyState.

Why it works this way

The illustration earns its place by carrying the category of the message. Empty, no results, failed, and finished are four different situations, and the drawing distinguishes them before the reader has read a word. That is also the whole argument for choosing it by meaning: an illustration picked for looks makes the region prettier and slower to understand. Replacing content rather than the region keeps the exit available. The most common empty state in a product is a filter that matched nothing, and the reader’s next action is to change the filter. A pattern that blanked the whole page would take the filter away with it.

Status and changelog

Last modified on September 7, 2026