Empty state

What stands where content would be when there is none: what this is, why it is empty, and what to do next.

First use

No locations yet

Add the places where you see clients, in person or by video.

No results

No clients found

Clients
ClientNext appointment

No clients match “zzz”

Check the spelling, or look in archived clients.

It is not a different look: it is the same block with different words. The title repeats what was searched, the action undoes it, and the action is not primary, because clearing a filter is nobody’s goal.

A section, and good news

Relevant notes

No notes yet

Notes written during an appointment are kept here.

Messages

No unread messages

You are up to date.

A frame that says something goes here

No documents yet

An ID card, an insurance policy, a referral letter.

variant="dashed" is the language of the drawn “+” tiles in a record’s documents: a dashed line is a place for something. So it is for first use only. On a search with no results a frame that invites making something says the wrong thing.

What did not load

Can’t load map

As drawn: the small size on a surface of its own, over the placeholder of what should have been there.

A field that has not been filled

Contacts

Location instructions

In the product this system was drawn for, a record just made is empty in place: “+ Add address” stands exactly where the address will be. That is not this component. It is a ghost Button with an icon, and needs no title and no sentence, because the heading over it has already said what is missing.

Which one

Empty, by where it is
WhereUse
A field of a record that has not been filleda ghost Button with “+”, in the field’s place
A section or a card with nothing in itEmptyState, sm
A table, a list or a page with nothing in itEmptyState, lg
A picture, a map or a chart that did not loadEmptyState, sm, on a surface of its own over the placeholder
A Select or a Combobox with no optionstheir own line: emptyText

What it says

Rules of content
RuleWhy
The title says what is not here“No locations yet”, never “Oops” or “Nothing here”.
The sentence says why, or what happens nextIt is the one place the feature is explained to someone who has not used it.
The action is the verb and the thing“Add location”, the same words as the button that makes one everywhere else.
Two actions at most, one primaryThe other way — an import, something to read — comes first and is quieter.
No results: repeat what was searched, and undoThe action clears the search and is not primary: clearing a filter is nobody’s goal.
Good news has no action“No unread messages” is where the reader wanted to be.
Loading is never emptyA Skeleton first, and this only once the answer is none.

Accessibility

The title is a heading, so the block is in the page’s outline; headingLevel is one below the heading it stands under. The icon is hidden; media is not, since an illustration may have words of its own, and takes its own alt. The block announces nothing by itself: when results change under a filter, how many were found is the caller’s live region to say. The circle is the pressed wash and not a surface, so one block is right on the page, on a card and in a panel, in both modes.

Using it

TSX
import { EmptyState, Button, Table } from 'alpenglow';

// First use: a table with nothing in it.
<Table
  …
  rows={locations}
  empty={
    <EmptyState
      icon={<Location size={24} />}
      title="No locations yet"
      description="Add the places where you see clients, in person or by video."
      action={<Button onClick={add}>Add location</Button>}
    />
  }
/>

// A section of a record.
<EmptyState size="sm" title="No notes yet" description="…" action={<Button variant="ghost" …>Add note</Button>} />
EmptyState props
PropTypeDefault
titlestringrequired
descriptionReactNode—
iconReactNode—
mediaReactNode — in the icon’s place—
actionReactNode—
secondaryActionReactNode—
size'sm' | 'lg''lg'
variant'plain' | 'dashed''plain'
headingLevel2 | 3 | 4 | 5 | 63
classNamestring—