Skip to content
Ndop UI

Empty State

Shows that there is nothing here yet, and what to do about it.

  • v1.0.0
  • SSR
  • Zoneless
  • 0.8 kB gzip

No projects yet

You haven't created a project yet. Start by creating your first one.

Read about projects
import { Component } from '@angular/core';
import { NdIcon } from '@ndop/core';
import { Button } from '@/ui/button/button';
import {
  Empty,
  EmptyContent,
  EmptyDescription,
  EmptyHeader,
  EmptyMedia,
  EmptyTitle,
} from '@/ui/empty/empty';

/** No projects yet, with actions to create one. */
@Component({
  selector: 'example-empty-demo',
  imports: [
    Button,
    Empty,
    EmptyContent,
    EmptyDescription,
    EmptyHeader,
    EmptyMedia,
    EmptyTitle,
    NdIcon,
  ],
  template: `
    <div ndEmpty class="border">
      <div ndEmptyHeader>
        <div ndEmptyMedia variant="icon"><svg ndIcon="folder-open"></svg></div>
        <h2 ndEmptyTitle>No projects yet</h2>
        <p ndEmptyDescription>
          You haven't created a project yet. Start by creating your first one.
        </p>
      </div>
      <div ndEmptyContent>
        <div class="flex gap-2">
          <button ndButton>Create project</button>
          <button ndButton variant="outline">Import project</button>
        </div>
        <a ndButton variant="link" href="#docs" size="sm"
          >Read about projects</a
        >
      </div>
    </div>
  `,
})
export class EmptyDemoExample {}

An empty state fills the space where content would be when there's none yet: no projects, no results, no messages. It says what's missing and what to do about it, with an optional icon or image and actions.

Installation

npx @ndop/cli add empty

Usage

import { Button } from '@/ui/button/button';
import {
  Empty,
  EmptyContent,
  EmptyDescription,
  EmptyHeader,
  EmptyMedia,
  EmptyTitle,
} from '@/ui/empty/empty';
<div ndEmpty class="border">
  <div ndEmptyHeader>
    <div ndEmptyMedia variant="icon"><svg ndIcon="folder-open"></svg></div>
    <h2 ndEmptyTitle>No projects yet</h2>
    <p ndEmptyDescription>
      You haven't created a project yet. Start by creating your first one.
    </p>
  </div>
  <div ndEmptyContent>
    <div class="flex gap-2">
      <button ndButton>Create project</button>
      <button ndButton variant="outline">Import project</button>
    </div>
    <a ndButton variant="link" href="#docs" size="sm"
      >Read about projects</a
    >
  </div>
</div>

Examples

No search results, with a way to clear the search.

No results

Nothing matches “quarterly report 2019”. Check the spelling or try other words.

import { Component, signal } from '@angular/core';
import { NdIcon } from '@ndop/core';
import { Button } from '@/ui/button/button';
import {
  Empty,
  EmptyContent,
  EmptyDescription,
  EmptyHeader,
  EmptyMedia,
  EmptyTitle,
} from '@/ui/empty/empty';

/**
 * No search results, which says what was searched and offers to clear
 * the search.
 */
@Component({
  selector: 'example-empty-search',
  imports: [
    Button,
    Empty,
    EmptyContent,
    EmptyDescription,
    EmptyHeader,
    EmptyMedia,
    EmptyTitle,
    NdIcon,
  ],
  template: `
    <div ndEmpty role="status">
      <div ndEmptyHeader>
        <div ndEmptyMedia variant="icon"><svg ndIcon="search"></svg></div>
        <h2 ndEmptyTitle>No results</h2>
        <p ndEmptyDescription>
          Nothing matches “{{ query() }}”. Check the spelling or try other
          words.
        </p>
      </div>
      <div ndEmptyContent>
        <button ndButton variant="outline" (click)="query.set('')">
          Clear search
        </button>
      </div>
    </div>
  `,
})
export class EmptySearchExample {
  protected readonly query = signal('quarterly report 2019');
}

Empty State avatar

An empty state with an avatar as its media.

LR

Lena is away

She'll reply to messages when she's back on Monday.

import { Component } from '@angular/core';
import { Avatar, AvatarFallback } from '@/ui/avatar/avatar';
import { Button } from '@/ui/button/button';
import {
  Empty,
  EmptyContent,
  EmptyDescription,
  EmptyHeader,
  EmptyMedia,
  EmptyTitle,
} from '@/ui/empty/empty';

/** An empty state with an avatar as its media, in the default style. */
@Component({
  selector: 'example-empty-avatar',
  imports: [
    Avatar,
    AvatarFallback,
    Button,
    Empty,
    EmptyContent,
    EmptyDescription,
    EmptyHeader,
    EmptyMedia,
    EmptyTitle,
  ],
  template: `
    <div ndEmpty>
      <div ndEmptyHeader>
        <div ndEmptyMedia>
          <span ndAvatar size="lg"><span ndAvatarFallback>LR</span></span>
        </div>
        <h2 ndEmptyTitle>Lena is away</h2>
        <p ndEmptyDescription>
          She'll reply to messages when she's back on Monday.
        </p>
      </div>
      <div ndEmptyContent>
        <button ndButton variant="outline" size="sm">Leave a message</button>
      </div>
    </div>
  `,
})
export class EmptyAvatarExample {}

Accessibility

Empty State has no keyboard interaction or focus handling of its own; it keeps the semantics of the element it's on.

API reference

Empty

[ndEmpty]

An empty state: shown where content would be, when there's none yet, with what to do about it.

Empty binding Type Default
[class]
Extra classes, merged last so they win.
string''
Data attribute Values
data-slotempty

EmptyHeader

[ndEmptyHeader]

An empty state's header: its media, title and description.

EmptyHeader binding Type Default
[class]
Extra classes, merged last so they win.
string''
Data attribute Values
data-slotempty-header

EmptyMedia

[ndEmptyMedia]

An image or icon above an empty state's title; variant="icon" puts an icon on a muted tile.

EmptyMedia binding Type Default
[variant]
Visual style.
'default' | 'icon''default'
[class]
Extra classes, merged last so they win.
string''
Data attribute Values
data-slotempty-icon
data-variant —

EmptyTitle

[ndEmptyTitle]

An empty state's title. Put it on the heading element that fits the page's outline.

EmptyTitle binding Type Default
[class]
Extra classes, merged last so they win.
string''
Data attribute Values
data-slotempty-title

EmptyDescription

[ndEmptyDescription]

What an empty state means, and what to do; links in it are underlined.

EmptyDescription binding Type Default
[class]
Extra classes, merged last so they win.
string''
Data attribute Values
data-slotempty-description

EmptyContent

[ndEmptyContent]

An empty state's actions, under its header.

EmptyContent binding Type Default
[class]
Extra classes, merged last so they win.
string''
Data attribute Values
data-slotempty-content

Agent notes

Do

  • Say what would be here, and how to get some: "No projects yet. Create one to get started."
  • Give it one main action, such as a button that creates the first item.
  • Tell search and filter results apart from a truly empty list, and offer to clear the filters.

Don't

  • Don't leave a blank area or a table with only headers instead.
  • Don't use it for errors; use an alert, which says what went wrong.