Skip to content
ShineUI
Install

EmptyState

Absence with a next step.

<sui-empty-state>FeedbackStable

About

Absence or outcome surface for a list with nothing in it, a search with no matches, a period that closed cleanly or an import that failed. Say what is missing and offer the next action in the actions slot; never apologize. Four variants share one anatomy, so a screen keeps its shape between empty and done.

Usage

<sui-empty-state heading="No open bills." description="Enter a bill to get started."> <sui-button slot="actions" variant="accent" label="Enter bill"></sui-button> </sui-empty-state> <script type="module"> import { defineCustomElements } from "@shineui/core/loader"; import "@shineui/core/shineui.css"; defineCustomElements(); </script>
import { SuiEmptyState } from "@shineui/react"; import "@shineui/core/shineui.css"; export function Example() { return ( <SuiEmptyState heading="No open bills." description="Enter a bill to get started."> <sui-button slot="actions" variant="accent" label="Enter bill"></sui-button> </SuiEmptyState> ); }
<script setup> import { SuiEmptyState } from "@shineui/vue"; import "@shineui/core/shineui.css"; </script> <template> <SuiEmptyState heading="No open bills." description="Enter a bill to get started."><sui-button slot="actions" variant="accent" label="Enter bill"></sui-button></SuiEmptyState> </template>
import { Component } from "@angular/core"; import { SuiEmptyState } from "@shineui/angular"; @Component({ standalone: true, imports: [SuiEmptyState], template: `<sui-empty-state heading="No open bills." description="Enter a bill to get started."><sui-button slot="actions" variant="accent" label="Enter bill"></sui-button></sui-empty-state>`, }) export class Example { }

Basic

Say what is missing and offer the next action; never apologize. The icon is aria-hidden, so the heading and body are the whole accessible content, and nothing here manages focus: when the action replaces this surface, the host page decides where focus lands. heading-level moves the h2 to h3 or h4.

<sui-empty-state heading="No open bills." description="Enter a bill to get started."> <sui-button slot="actions" variant="accent" label="Enter bill"></sui-button> </sui-empty-state>

Variants

empty, success, error and not-found share one anatomy, so a screen does not switch shapes between empty and done. success is navy, never green, and only error carries role="alert", so only a failed operation interrupts a screen reader; do not reach for error on a merely empty list.

<div style="display:grid;grid-template-columns:1fr 1fr;gap:14px;"> <sui-empty-state heading="No open bills." description="Enter a bill to get started."></sui-empty-state> <sui-empty-state variant="success" heading="July is closed" description="All accounts reconciled."></sui-empty-state> <sui-empty-state variant="error" heading="Import failed" description="The bank returned no data for 4402."></sui-empty-state> <sui-empty-state variant="not-found" heading="No such invoice" description="INV-9910 is not in this ledger."></sui-empty-state> </div>

Rich body and actions

Put markup in the default slot when the body needs more than a sentence; a filled slot replaces description rather than stacking under it. The actions slot takes a row of buttons, one accent button at most.

No results for riverbend in July. Try a wider date range.
<sui-empty-state variant="not-found" heading="No matches." description="Ignored while the slot is filled."> No results for <b>riverbend</b> in July. Try a wider date range. <sui-button slot="actions" variant="accent" label="Clear filters"></sui-button> <sui-button slot="actions" variant="ghost" label="Search all years"></sui-button> </sui-empty-state>

Compact and bare

compact tightens the padding and the icon well for a table body or a narrow column. bare drops the card frame, for a surface that already has one.

<div style="display:grid;grid-template-columns:1fr 1fr;gap:14px;align-items:start;"> <sui-empty-state compact heading="No attachments" description="Drop a file to add one."></sui-empty-state> <div style="background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:6px;"> <sui-empty-state bare compact variant="not-found" heading="No unmatched lines" description="Every line in July has a match."></sui-empty-state> </div> </div>

API

<sui-empty-state>

Properties

PropertyAttributeTypeDefaultDescription
barebarebooleanfalseDrops the card frame (transparent, no border).
compactcompactbooleanfalseTighter padding, 40px icon well, 13.5px heading.
descriptiondescriptionstringstring | undefinedSupporting line, max 360px wide. Ignored when the default slot is filled.
headingheadingstring''Headline. Named heading because title is the native tooltip attribute.
headingLevelheading-level2 | 3 | 42Heading level of the title element, 2 to 4. The size does not change with it.
iconiconstringstring | undefinedFont Awesome class overriding the variant icon.
variantvariant"empty" | "error" | "not-found" | "success"'empty'Outcome flavour: empty, success (the brand, never a green), error (the deep accent) or not-found. Sets the icon well colors and the default icon. Only error renders role="alert", so only a failed operation interrupts a screen reader; do not use it for a merely empty list. The icon is aria-hidden, so the heading and body are the whole accessible content.

Slots

SlotDescription
(default)Body content with markup, for example "No results for **riverbend**" with a clear-filters link. It shares the body position with description, so it replaces it rather than stacking.
actionsButtons rendered in a row under the description (one accent button at most). Nothing here manages focus: when an action replaces this surface, the host page decides where focus lands.

Theming

Every design token this element can render with, read from its own stylesheets and the ones it imports. Set a token on :root or on any ancestor and every use below follows it. The values shown are the ones in the theme you are viewing. The list is read per stylesheet, so an element that imports a shared drawing module lists that module's tokens too, whether or not it paints with all of them.

See also