Skip to content
UI

Empty

The parts of an empty state, for a page or a region that has nothing to show yet.

@zenoxai/ui/components/empty Markdown
No assets yet
Connect a cloud account or import a CSV to build the asset inventory.
<Empty>
  <EmptyHeader>
    <EmptyMedia variant="icon">
      <ServerIcon />
    </EmptyMedia>
    <EmptyTitle>No assets yet</EmptyTitle>
    <EmptyDescription>
      Connect a cloud account or import a CSV to build the asset inventory.
    </EmptyDescription>
  </EmptyHeader>
  <EmptyContent>
    <div className="flex gap-2">
      <Button variant="outline">Connect account</Button>
      <Button variant="outline">
        <UploadIcon data-icon="inline-start" />
        Import CSV
      </Button>
    </div>
  </EmptyContent>
</Empty>

Usage

import { ServerIcon } from "lucide-react"

import { Button } from "@zenoxai/ui/components/button"
import {
  Empty,
  EmptyContent,
  EmptyDescription,
  EmptyHeader,
  EmptyMedia,
  EmptyTitle,
} from "@zenoxai/ui/components/empty"

export function NoAssets() {
  return (
    <Empty>
      <EmptyHeader>
        <EmptyMedia variant="icon">
          <ServerIcon />
        </EmptyMedia>
        <EmptyTitle>No assets yet</EmptyTitle>
        <EmptyDescription>
          Connect a cloud account to build the inventory.
        </EmptyDescription>
      </EmptyHeader>
      <EmptyContent>
        <Button>Connect account</Button>
      </EmptyContent>
    </Empty>
  )
}

Use Empty for a whole page or a large region that is empty because the user has not set anything up: no assets, no integrations, no reports. Say what is missing in the title, why it matters or what fills it in the description, and offer the first step in EmptyContent.

EmptyMedia variant="icon" draws the icon on a muted square. The default variant renders the media as is, for an illustration.

For lists, tables and cards, use the patterns built on these parts. They fix the spacing and the copy rules, and keep an empty result apart from a failed request:

Outlined

Add a dashed border when the empty state sits among other content and needs an edge, such as a region of a dashboard. Links in EmptyDescription are underlined.

No scans scheduled
Schedule a scan to check external domains for exposed services. Read about scan scopes first.
<Empty className="border border-dashed border-border">
  <EmptyHeader>
    <EmptyMedia variant="icon">
      <RadarIcon />
    </EmptyMedia>
    <EmptyTitle>No scans scheduled</EmptyTitle>
    <EmptyDescription>
      Schedule a scan to check external domains for exposed services. Read
      about <a href="#accessibility">scan scopes</a> first.
    </EmptyDescription>
  </EmptyHeader>
  <EmptyContent>
    <Button variant="outline" size="sm">
      Schedule scan
    </Button>
  </EmptyContent>
</Empty>

Accessibility

  • EmptyTitle renders a <div>, not a heading. When the empty state replaces the main content of a page, put a heading inside it, <EmptyTitle><h2>No assets yet</h2></EmptyTitle>, so the page keeps its outline.
  • The icon is decorative. The title must say on its own what is empty.

API reference

Generated from the TypeScript source. className, style and children are accepted everywhere and omitted below.

Empty

Empty is the layout of an empty state: a centered column with EmptyMedia, an EmptyHeader holding EmptyTitle and EmptyDescription, and EmptyContent for actions. For a list, table or card with no data, use the ListEmptyState pattern, which builds on it; for a failed load, ListErrorState.

No props of its own. Accepts the props of the element it renders.

EmptyHeader

No props of its own. Accepts the props of the element it renders.

EmptyTitle

No props of its own. Accepts the props of the element it renders.

EmptyDescription

No props of its own. Accepts the props of the element it renders.

EmptyContent

EmptyContent holds the actions under the text, such as a button that creates the first item.

No props of its own. Accepts the props of the element it renders.

EmptyMedia

EmptyMedia is the illustration or icon above the title.

PropTypeDefault
variant"default" | "icon" | null

`default` shows the media as it is, for an illustration; `icon` sets an icon in a 32px muted tile.

default