Skip to the content
BooleanPress UI

Misc

Empty

Fills the space of a list, table or page that has nothing to show yet, and says what to do next.

Import

import { Empty, EmptyHeader, EmptyTitle, EmptyDescription, EmptyContent, EmptyMedia } from "@booleanpress/ui/empty"

Usage

Build the message from its parts: a header with an optional icon, a title and a description, then the content for the actions.

import { MailIcon } from "lucide-react"
import { Button } from "@booleanpress/ui/button"
import {
  Empty,
  EmptyContent,
  EmptyDescription,
  EmptyHeader,
  EmptyMedia,
  EmptyTitle,
} from "@booleanpress/ui/empty"

export function NoEmails() {
  return (
    <Empty>
      <EmptyHeader>
        <EmptyMedia variant="icon">
          <MailIcon />
        </EmptyMedia>
        <EmptyTitle>No emails yet</EmptyTitle>
        <EmptyDescription>Emails appear here as soon as your site sends one.</EmptyDescription>
      </EmptyHeader>
      <EmptyContent>
        <Button>Send a test email</Button>
      </EmptyContent>
    </Empty>
  )
}

Empty has no border or background of its own, only a dashed border style: add border for the dashed frame. EmptyMedia takes variant="icon" for an icon in a rounded tile, or the default for a bare icon or picture.

Say which kind of empty it is. A first run (nothing created yet) offers the action that creates; a search with no result offers to clear the search; an error is not an empty state, and belongs in an Alert.

Examples

Basic

An icon tile, a title, a description and one action.

Bordered

className="border" draws the dashed frame; two actions sit side by side.

No results

A bare icon and a way back out of a search that found nothing.

Accessibility

Semantics
Plain divs, with no roles. EmptyTitle and EmptyDescription are not headings or paragraphs, so the page's heading levels are untouched.
Labels
The text is the content. Wrap the title in the heading level your page needs if the empty state is the main content of a section.
Focus
Not focusable; the buttons inside it are in the tab order. Nothing moves focus when the empty state appears.
Known limits
  • An empty state that replaces a list after a search or filter is not announced. Announce the result count in a live region the page owns.
  • EmptyTitle and EmptyDescription are divs (stock), so a screen reader's heading navigation skips them.

Keyboard

Keyboard
KeyBehaviour

API

Empty

Renders a div and passes it every other prop.

EmptyHeader

Renders a div and passes it every other prop.

EmptyTitle

Renders a div and passes it every other prop.

EmptyDescription

Renders a p and passes it every other prop.

EmptyContent

Renders a div and passes it every other prop.

EmptyMedia

Renders a div and passes it every other prop.

Every part takes className, merged with its defaults by cn(), and ref, which reaches the element it renders.

Data attributes: data-slot="empty" (Empty), data-slot="empty-header" (EmptyHeader), data-slot="empty-title" (EmptyTitle), data-slot="empty-description" (EmptyDescription), data-slot="empty-content" (EmptyContent), data-slot="empty-icon" (EmptyMedia), and data-variant.

Theming

The tile is --muted, the description --muted-foreground. The dashed border takes its colour from --border when you add border.

The tokens its classes read. Change their values in your theme, and it follows.

Theme tokens
TokenUsed for
--foregroundtext
--mutedbackground
--muted-foregroundtext
--primarytext