Skip to main content
Yoummday Light Light Dark System

Empty State

<sl-empty-state> | SlEmptyState
Since 3.9.1 stable

Displays a centered empty state with optional icon or image, headline, and message. Content is set via properties only.

Content properties (icon, imageSrc, headline, message) are property-only and are not available as HTML attributes. In plain HTML, assign them with JavaScript as shown in the examples below. Use the variant attribute to align content — centered (default), left, or right.

<sl-empty-state id="empty-state-demo"></sl-empty-state>

<script type="module">
  Object.assign(document.getElementById('empty-state-demo'), {
    icon: 'mdi:inbox-outline',
    headline: 'No items yet',
    message: 'Add your first item to get started.'
  });
</script>
import SlEmptyState from '@yoummday/ymmd-shoelace/dist/react/empty-state';

const App = () => (
  <SlEmptyState
    icon="mdi:inbox-outline"
    headline="No items yet"
    message="Add your first item to get started."
  />
);

Examples

Set only the properties you need. Each content prop is independent — if it is not set, that section is not rendered. Use icon or imageSrc, not both; only one graphic is shown at a time. When headline is set, it is used as the image alt text and the icon aria-label.

Variants

Use the variant attribute to horizontally align the icon or image, headline, and message. Accepts centered (default), left, or right.

Centered
Left
Right
<div class="empty-state-variants">
  <div>
    <sl-txt span>Centered</sl-txt>
    <sl-empty-state id="empty-state-centered"></sl-empty-state>
  </div>
  <div>
    <sl-txt span>Left</sl-txt>
    <sl-empty-state id="empty-state-left" variant="left"></sl-empty-state>
  </div>
  <div>
    <sl-txt span>Right</sl-txt>
    <sl-empty-state id="empty-state-right" variant="right"></sl-empty-state>
  </div>
</div>

<script type="module">
  for (const id of ['empty-state-centered', 'empty-state-left', 'empty-state-right']) {
    Object.assign(document.getElementById(id), {
      icon: 'mdi:inbox-outline',
      headline: 'No items yet',
      message: 'Add your first item to get started.'
    });
  }
</script>

<style>
  .empty-state-variants {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
    gap: var(--sl-spacing-large);
    width: 100%;
  }

  .empty-state-variants > div {
    display: flex;
    flex-direction: column;
    gap: var(--sl-spacing-x-small);
  }
</style>
import SlEmptyState from '@yoummday/ymmd-shoelace/dist/react/empty-state';

const props = {
  icon: 'mdi:inbox-outline',
  headline: 'No items yet',
  message: 'Add your first item to get started.'
};

const App = () => (
  <>
    <SlEmptyState {...props} />
    <SlEmptyState {...props} variant="left" />
    <SlEmptyState {...props} variant="right" />
  </>
);

With image

When icon is not set, set the imageSrc property with a URL. If both are set, icon takes precedence. Images are displayed at 160×160px by default; icons render at 52px.

<sl-empty-state id="empty-state-image-demo"></sl-empty-state>

<script type="module">
  Object.assign(document.getElementById('empty-state-image-demo'), {
    imageSrc: 'https://picsum.photos/160',
    headline: 'No results',
    message: 'Try adjusting your filters.'
  });
</script>

Override the graphic size with the graphic CSS part.

<sl-empty-state id="empty-state-image-size" class="empty-state-image-size"></sl-empty-state>

<script type="module">
  Object.assign(document.getElementById('empty-state-image-size'), {
    imageSrc: 'https://picsum.photos/160',
    headline: 'No results',
    message: 'Try adjusting your filters.'
  });
</script>

<style>
  .empty-state-image-size::part(graphic) {
    width: 6rem;
    height: 6rem;
  }
</style>
import SlEmptyState from '@yoummday/ymmd-shoelace/dist/react/empty-state';

const css = `
  .empty-state-image-size::part(graphic) {
    width: 6rem;
    height: 6rem;
  }
`;

const App = () => (
  <>
    <style>{css}</style>
    <SlEmptyState
      className="empty-state-image-size"
      imageSrc="https://picsum.photos/160"
      headline="No results"
      message="Try adjusting your filters."
    />
  </>
);

Layout

The host applies padding-block: var(--sl-spacing-large) and a default min-height of 8rem. Use --empty-state-min-height to override the minimum height, and padding-block to override block padding.

<sl-empty-state id="empty-state-layout-demo" class="empty-state-layout-demo"></sl-empty-state>

<script type="module">
  Object.assign(document.getElementById('empty-state-layout-demo'), {
    icon: 'mdi:inbox-outline',
    headline: 'No items yet',
    message: 'Add your first item to get started.'
  });
</script>

<style>
  .empty-state-layout-demo {
    --empty-state-min-height: 12rem;
    padding-block: var(--sl-spacing-2x-large);
  }
</style>
import SlEmptyState from '@yoummday/ymmd-shoelace/dist/react/empty-state';

const App = () => (
  <SlEmptyState
    icon="mdi:inbox-outline"
    headline="No items yet"
    message="Add your first item to get started."
    style={{ '--empty-state-min-height': '12rem', paddingBlock: 'var(--sl-spacing-2x-large)' }}
  />
);

No content

When no properties are set, nothing is rendered inside the component. The host still reserves space via its default 8rem min-height and block padding.

<sl-empty-state></sl-empty-state>
import SlEmptyState from '@yoummday/ymmd-shoelace/dist/react/empty-state';

const App = () => <SlEmptyState />;

Single property

Icon only
Image only
Headline only
Message only
<div class="empty-state-combos">
  <div>
    <sl-txt span>Icon only</sl-txt>
    <sl-empty-state id="empty-state-icon-only"></sl-empty-state>
  </div>
  <div>
    <sl-txt span>Image only</sl-txt>
    <sl-empty-state id="empty-state-image-only"></sl-empty-state>
  </div>
  <div>
    <sl-txt span>Headline only</sl-txt>
    <sl-empty-state id="empty-state-headline-only"></sl-empty-state>
  </div>
  <div>
    <sl-txt span>Message only</sl-txt>
    <sl-empty-state id="empty-state-message-only"></sl-empty-state>
  </div>
</div>

<script type="module">
  Object.assign(document.getElementById('empty-state-icon-only'), {
    icon: 'mdi:inbox-outline'
  });
  Object.assign(document.getElementById('empty-state-image-only'), {
    imageSrc: 'https://picsum.photos/160'
  });
  Object.assign(document.getElementById('empty-state-headline-only'), {
    headline: 'No items yet'
  });
  Object.assign(document.getElementById('empty-state-message-only'), {
    message: 'Add your first item to get started.'
  });
</script>

<style>
  .empty-state-combos {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
    gap: var(--sl-spacing-large);
    width: 100%;
  }

  .empty-state-combos > div {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sl-spacing-x-small);
  }
</style>
import SlEmptyState from '@yoummday/ymmd-shoelace/dist/react/empty-state';

const App = () => (
  <>
    <SlEmptyState icon="mdi:inbox-outline" />
    <SlEmptyState imageSrc="https://picsum.photos/160" />
    <SlEmptyState headline="No items yet" />
    <SlEmptyState message="Add your first item to get started." />
  </>
);

Pairs

Icon + headline
Icon + message
Image + headline
Image + message
Headline + message
<div class="empty-state-combos">
  <div>
    <sl-txt span>Icon + headline</sl-txt>
    <sl-empty-state id="empty-state-icon-headline"></sl-empty-state>
  </div>
  <div>
    <sl-txt span>Icon + message</sl-txt>
    <sl-empty-state id="empty-state-icon-message"></sl-empty-state>
  </div>
  <div>
    <sl-txt span>Image + headline</sl-txt>
    <sl-empty-state id="empty-state-image-headline"></sl-empty-state>
  </div>
  <div>
    <sl-txt span>Image + message</sl-txt>
    <sl-empty-state id="empty-state-image-message"></sl-empty-state>
  </div>
  <div>
    <sl-txt span>Headline + message</sl-txt>
    <sl-empty-state id="empty-state-headline-message"></sl-empty-state>
  </div>
</div>

<script type="module">
  Object.assign(document.getElementById('empty-state-icon-headline'), {
    icon: 'mdi:inbox-outline',
    headline: 'No items yet'
  });
  Object.assign(document.getElementById('empty-state-icon-message'), {
    icon: 'mdi:inbox-outline',
    message: 'Add your first item to get started.'
  });
  Object.assign(document.getElementById('empty-state-image-headline'), {
    imageSrc: 'https://picsum.photos/160',
    headline: 'No results'
  });
  Object.assign(document.getElementById('empty-state-image-message'), {
    imageSrc: 'https://picsum.photos/160',
    message: 'Try adjusting your filters.'
  });
  Object.assign(document.getElementById('empty-state-headline-message'), {
    headline: 'Nothing here',
    message: 'Content will appear when data is available.'
  });
</script>

<style>
  .empty-state-combos {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
    gap: var(--sl-spacing-large);
    width: 100%;
  }

  .empty-state-combos > div {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sl-spacing-x-small);
  }
</style>
import SlEmptyState from '@yoummday/ymmd-shoelace/dist/react/empty-state';

const App = () => (
  <>
    <SlEmptyState icon="mdi:inbox-outline" headline="No items yet" />
    <SlEmptyState icon="mdi:inbox-outline" message="Add your first item to get started." />
    <SlEmptyState imageSrc="https://picsum.photos/160" headline="No results" />
    <SlEmptyState imageSrc="https://picsum.photos/160" message="Try adjusting your filters." />
    <SlEmptyState headline="Nothing here" message="Content will appear when data is available." />
  </>
);

Triples

Icon + headline + message
Image + headline + message
<div class="empty-state-combos">
  <div>
    <sl-txt span>Icon + headline + message</sl-txt>
    <sl-empty-state id="empty-state-icon-all"></sl-empty-state>
  </div>
  <div>
    <sl-txt span>Image + headline + message</sl-txt>
    <sl-empty-state id="empty-state-image-all"></sl-empty-state>
  </div>
</div>

<script type="module">
  Object.assign(document.getElementById('empty-state-icon-all'), {
    icon: 'mdi:inbox-outline',
    headline: 'No items yet',
    message: 'Add your first item to get started.'
  });
  Object.assign(document.getElementById('empty-state-image-all'), {
    imageSrc: 'https://picsum.photos/160',
    headline: 'No results',
    message: 'Try adjusting your filters.'
  });
</script>

<style>
  .empty-state-combos {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
    gap: var(--sl-spacing-large);
    width: 100%;
  }

  .empty-state-combos > div {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sl-spacing-x-small);
  }
</style>
import SlEmptyState from '@yoummday/ymmd-shoelace/dist/react/empty-state';

const App = () => (
  <>
    <SlEmptyState
      icon="mdi:inbox-outline"
      headline="No items yet"
      message="Add your first item to get started."
    />
    <SlEmptyState
      imageSrc="https://picsum.photos/160"
      headline="No results"
      message="Try adjusting your filters."
    />
  </>
);

With table and card

Use a card to frame a table and render the empty state below the column headers when there are no rows to show.

Team members
Name Email Role
<sl-card class="empty-state-table-card">
  <div slot="header">
    <sl-txt h3>Team members</sl-txt>
  </div>

  <sl-table>
    <sl-table-row slot="head">
      <sl-table-cell>Name</sl-table-cell>
      <sl-table-cell>Email</sl-table-cell>
      <sl-table-cell>Role</sl-table-cell>
    </sl-table-row>
  </sl-table>

  <sl-empty-state id="empty-state-table-demo"></sl-empty-state>
</sl-card>

<script type="module">
  Object.assign(document.getElementById('empty-state-table-demo'), {
    icon: 'mdi:account-group-outline',
    headline: 'No team members yet',
    message: 'Invite colleagues to collaborate on this project.'
  });
</script>

<style>
  .empty-state-table-card {
    width: 100%;
  }

  .empty-state-table-card::part(body) {
    display: flex;
    flex-direction: column;
    padding: 0;
  }

  .empty-state-table-card sl-empty-state {
    --empty-state-min-height: 12rem;
  }
</style>
import SlCard from '@yoummday/ymmd-shoelace/dist/react/card';
import SlEmptyState from '@yoummday/ymmd-shoelace/dist/react/empty-state';
import SlTable from '@yoummday/ymmd-shoelace/dist/react/table';
import SlTableCell from '@yoummday/ymmd-shoelace/dist/react/table-cell';
import SlTableRow from '@yoummday/ymmd-shoelace/dist/react/table-row';
import SlTxt from '@yoummday/ymmd-shoelace/dist/react/txt';

const css = `
  .empty-state-table-card {
    width: 100%;
  }

  .empty-state-table-card::part(body) {
    display: flex;
    flex-direction: column;
    padding: 0;
  }

  .empty-state-table-card sl-empty-state {
    --empty-state-min-height: 12rem;
  }
`;

const App = () => (
  <>
    <style>{css}</style>
    <SlCard className="empty-state-table-card">
      <div slot="header">
        <SlTxt h3>Team members</SlTxt>
      </div>
      <SlTable>
        <SlTableRow slot="head">
          <SlTableCell>Name</SlTableCell>
          <SlTableCell>Email</SlTableCell>
          <SlTableCell>Role</SlTableCell>
        </SlTableRow>
      </SlTable>
      <SlEmptyState
        icon="mdi:account-group-outline"
        headline="No team members yet"
        message="Invite colleagues to collaborate on this project."
      />
    </SlCard>
  </>
);

Importing

If you’re using the autoloader or the traditional loader, you can ignore this section. Otherwise, feel free to use any of the following snippets to cherry pick this component.

Script Import Bundler React

To import this component from the CDN using a script tag:

<script type="module" src="https://v3-10-10.yoummday-theme.pages.dev/components/empty-state/empty-state.js"></script>

To import this component from the CDN using a JavaScript import:

import 'https://v3-10-10.yoummday-theme.pages.dev/components/empty-state/empty-state.js';

To import this component using a bundler:

import '@yoummday/ymmd-shoelace/dist/components/empty-state/empty-state.js';

To import this component as a React component:

import SlEmptyState from '@yoummday/ymmd-shoelace/dist/react/empty-state';

Properties

Name Description Reflects Type Default
icon The icon to show, passed to <sl-icon name="...">. Use icon or imageSrc, not both. Omitted when empty. string ''
imageSrc Image src URL. Use icon or imageSrc, not both. Omitted when empty. string ''
headline The headline text. Omitted when empty. Also used as the image alt and icon aria-label when set. string ''
message The message text shown below the headline. Omitted when empty. string ''
variant Aligns the empty state content. Accepts centered, left, or right. 'centered' | 'left' | 'right' 'centered'
updateComplete A read-only promise that resolves when the component has finished updating.

Learn more about attributes and properties.

Custom Properties

Name Description Default
--empty-state-min-height The minimum height of the host. 8rem

Learn more about customizing CSS custom properties.

Parts

Name Description
content The container for the empty state content.
graphic The wrapper around the icon or image.
headline The headline element.
message The message element.

Learn more about customizing CSS parts.

Dependencies

This component automatically imports the following dependencies.

  • <sl-icon>
  • <sl-txt>