---
id: "packages/active-ui/empty"
title: "Empty"
description: "What a list or a page shows when it has nothing to show, with the reason and the way forward."
url: "/packages/active-ui/empty"
locale: "en"
revision: "dcdbe53cea9a8e36"
---

# Empty

An empty state takes the place of content that is not there: a list without records yet, a search
without results, a folder without files. It says why, and offers the next step. It is not a loading
state: while data loads, show a spinner or a loading screen, and the empty state only once you know
there is nothing.

**Example: Nothing yet, and nothing found**

Client: Runs entirely in your browser. Source: `examples/ui/empty.tsx`.

```tsx
// apps/docs/examples/ui/empty.tsx
'use client';

import {useState} from 'react';
import {FolderOpenIcon, SearchXIcon} from 'lucide-react';

import {Button} from '@workspace/active-ui/components/primitives/button';
import {
  Empty,
  EmptyContent,
  EmptyDescription,
  EmptyHeader,
  EmptyMedia,
  EmptyTitle,
} from '@workspace/active-ui/components/primitives/empty';

/**
 * What a list shows when it has nothing to show, and why: no records yet,
 * with the action that creates the first; and no results for a search, with
 * the way back. An empty state is no loading state.
 */
export default function EmptyExample() {
  const [query, setQuery] = useState('rotterdam');
  return (
    <div className="grid w-full max-w-2xl gap-4 sm:grid-cols-2">
      <Empty className="border">
        <EmptyHeader>
          <EmptyMedia variant="icon">
            <FolderOpenIcon aria-hidden />
          </EmptyMedia>
          <EmptyTitle>No schemes yet</EmptyTitle>
          <EmptyDescription>
            Create a scheme to add participants and send statements.
          </EmptyDescription>
        </EmptyHeader>
        <EmptyContent>
          <Button>Create a scheme</Button>
        </EmptyContent>
      </Empty>
      <Empty className="border">
        <EmptyHeader>
          <EmptyMedia variant="icon">
            <SearchXIcon aria-hidden />
          </EmptyMedia>
          <EmptyTitle>
            {query ? `Nothing matches “${query}”` : 'Search cleared'}
          </EmptyTitle>
          <EmptyDescription>
            Check the spelling, or search for a participant number instead.
          </EmptyDescription>
        </EmptyHeader>
        <EmptyContent>
          <Button
            variant="outline"
            disabled={!query}
            onClick={() => setQuery('')}
          >
            Clear the search
          </Button>
        </EmptyContent>
      </Empty>
    </div>
  );
}
```

## Usage

```tsx
import {
  Empty,
  EmptyContent,
  EmptyDescription,
  EmptyHeader,
  EmptyMedia,
  EmptyTitle,
} from '@workspace/active-ui/components/primitives/empty';

<Empty>
  <EmptyHeader>
    <EmptyMedia variant="icon">
      <FolderOpenIcon aria-hidden />
    </EmptyMedia>
    <EmptyTitle>No schemes yet</EmptyTitle>
    <EmptyDescription>Create a scheme to add participants.</EmptyDescription>
  </EmptyHeader>
  <EmptyContent>
    <Button>Create a scheme</Button>
  </EmptyContent>
</Empty>;
```

## Anatomy

- `Empty`: the centred area; give it a `border` to frame it.
- `EmptyHeader` with `EmptyMedia` (`variant`: `default`, or `icon` for an icon on a muted tile),
  `EmptyTitle` and `EmptyDescription` (links in it are underlined).
- `EmptyContent`: the actions.

## What your application provides

- The reason, specific to the situation: "No schemes yet" differs from "Nothing matches
  rotterdam", and from "You have no access".
- The next step, if there is one, as an action.
- The moment: show the empty state only after loading has finished without results.

## Accessibility

An empty state is ordinary content. When it replaces a list after a search, announce the change,
for example with a polite live region near the search field, because a reader who typed does not
see the list change.

## API

**Empty**

| Prop | Type | Required | Description |
| --- | --- | --- | --- |

Empty has no props of its own.

**EmptyHeader**

| Prop | Type | Required | Description |
| --- | --- | --- | --- |

EmptyHeader has no props of its own.

**EmptyTitle**

| Prop | Type | Required | Description |
| --- | --- | --- | --- |

EmptyTitle has no props of its own.

**EmptyDescription**

| Prop | Type | Required | Description |
| --- | --- | --- | --- |

EmptyDescription has no props of its own.

**EmptyContent**

| Prop | Type | Required | Description |
| --- | --- | --- | --- |

EmptyContent has no props of its own.

**EmptyMedia**

| Prop | Type | Required | Description |
| --- | --- | --- | --- |
| `variant` | `"default" \| "icon" \| null` | no | `default` as is, or `icon` for an icon on a muted tile. |

> [!NOTE]
> **Based on shadcn/ui**
>
> This page adapts the Empty documentation of shadcn/ui (MIT licence) to this
> package; see [Third-party notices](/third-party-notices).
