Skip to content

CdsEmptyState

An empty state explains why there is no content on the screen and suggests the next step: no search results, an empty list, a loading error. It is assembled from a media area, headings, a description and an action button.

Storybook GitLab Figma
Test coverage: 100% — good coverage
API in specs
32 / 32 props, events, slots and exposed members with a test
Test cases
36 unit · 0 browser
Known bugs
1 pinned by an it.fails test
Code coverage
100% lines · 98.3% branches measured in v4.0.0-alpha.13
A11y (axe)
9 recommendations in 12 stories measured in v4.0.0-alpha.11

For a short message about the result of an operation take CdsToast, and while the data is still loading show CdsSkeletonLoader instead of an empty state.

Anatomy ​

An empty state is a vertical stack of zones. Each zone appears only when its prop or slot is set, so you pick the composition that fits the situation: from a single heading line to the full set with media and a button.

Variations ​

Content ​

Every text zone has its own prop: headline is the large accent ("404", "Empty"), title states the situation, text gives the details and hints what to do. The width of the text is capped by text-width (500 by default), so a long description does not stretch across the whole screen.

Media ​

The icon prop shows an icon, image shows an image (it wins over the icon). The size of the media comes from size: 96 for an icon and 200 for an image by default. The color of the icon is changed by the color prop.

Illustrations ​

Legacy illustrations from the @central-design-system/illustrations package (CDS 3): the illustration prop accepts the kebab-case name of a globally registered component (they are registered through the illustrations option of createCds). You can render your own illustration through the illustration slot.

Alignment ​

The justify prop pushes the content to the edge of the container: start, center (default) or end. The dashed frame in the demo shows the bounds of the container.

Actions ​

The action-text prop adds a button below the content; a click on it arrives as the click:action event. When there is more than one action, render your own buttons in the actions slot — bind props.onClick from the slot to the main button so that the click:action event keeps working.

Slots ​

Slots replace the content coming from props when you need full control over the markup.

SlotDescription
mediaMedia area. Replaces the content from icon and image
illustrationIllustration. Replaces the content from illustration
headlineAccent heading. Replaces the text from headline
titleHeading. Replaces the text from title
textDescription. Replaces the text from text
descriptionExtra description. Replaces the text from description
defaultArbitrary content between the description and the actions
actionsAction buttons; receives props with an onClick handler

Guidelines ​

Scenarios ​

Search with no results ​

When nothing matches the query, an empty state replaces the list. The button from action-text clears the query on click:action — the user returns to the full list in one click. Try typing a query that is not in the list.

Empty list ​

The first visit to a section is a reason not to apologize for the emptiness but to help the user start: title names the situation, text promises a result, and the button from action-text creates the first record. Once a record is added, the list replaces the placeholder.

Loading error ​

If the data failed to load, explain the reason and let the user retry right there. The button in the actions slot shows loading while the retry is in flight, and props.onClick from the slot keeps the click:action event.

404 page ​

headline prints the large error code, and href (or to for vue-router) is passed to the action button — it works as a link and takes the user away from the dead-end page.

API ​

Props

NameTypeDefaultDescription
actionTextstring | undefined—Text of the action button. When set, a button is rendered below the content.
bgColorstring | undefined—Background color of the component
colorstring | undefined—Component color
contentstring | number | undefined—Content displayed in the component.
descriptionstring | undefined—Description
headlinestring | undefined—Large accent heading above the main heading.
heightstring | number | undefined—Component height
hrefstring | undefined—The href attribute of the link. When set, the component behaves as a regular link
iconIconValue | undefined—Icon in the media area.
illustrationstring | undefined—Legacy illustration from the @central-design-system/illustrations package (CDS 3): the kebab-case name of a globally registered component, for example rocket. Illustrations are registered through the illustrations option of createCds.
imagestring | undefined—Source of the image in the media area (takes priority over icon).
justify"start" | "end" | "center" | undefined'center'Horizontal alignment of the content: start, center, end.
maxHeightstring | number | undefined—Maximum component height
maxWidthstring | number | undefined—Maximum component width
minHeightstring | number | undefined—Minimum component height
minWidthstring | number | undefined—Minimum component width
sizenumber | "xs" | "sm" | "md" | "lg" | "xl" | undefined'md'Size of the component
textstring | number | undefined—Text displayed in the component.
textWidthstring | number | undefined500Maximum width of the description block.
themestring | undefined—Component theme
titlestring | undefined—Heading.
toLinkTo | undefined—Target route or route location object for RouterLink. When set, the component behaves as a RouterLink
widthstring | number | undefined—Component width

Events

NameTypeDescription
click:action[event: MouseEvent]Click on the action button.

Slots

NameTypeDescription
actions{ props: { onClick: (event: MouseEvent) => void; }; }Actions slot; receives props with an onClick handler to bind to your own element.
defaultanyArbitrary content between the description and the actions.
descriptionanyDescription slot (instead of the description prop).
headlineanyAccent heading slot (instead of the headline prop).
illustrationanyMedia area slot for an illustration (instead of the illustration prop).
mediaanyMedia area slot (instead of the image / icon props).
textanyDescription slot (instead of the text prop).
titleanyHeading slot (instead of the title prop).