Skip to content
UI

List Empty State

The state of a list, table or card whose request succeeded and returned nothing.

@zenoxai/ui/patterns/list-empty-state Markdown
No alerts yet
Alerts appear here as soon as a connector reports a detection.
<ListEmptyState
  title="No alerts yet"
  description="Alerts appear here as soon as a connector reports a detection."
/>

Usage

import { ListEmptyState } from "@zenoxai/ui/patterns/list-empty-state"
import { ListErrorState } from "@zenoxai/ui/patterns/list-error-state"

export function AlertList({ query }: { query: AlertsQuery }) {
  if (query.isError) return <ListErrorState onRetry={query.refetch} />
  if (query.data.length === 0) {
    return (
      <ListEmptyState
        title="No alerts yet"
        description="Alerts appear here as soon as a connector reports a detection."
      />
    )
  }
  return <AlertsTable alerts={query.data} />
}

Render ListEmptyState only when the request succeeded and came back empty. When the request failed, render ListErrorState: an empty list tells the user there is nothing to act on, and showing it for a failure hides a problem. While the request is in flight, show a skeleton, not the empty state.

title and description arrive already translated. Write the title as a fact (“No alerts yet”), and the description as what fills the list or what to do next. Pass an action only when the user can change the outcome from here.

For a whole page that has nothing set up yet, such as an onboarding screen, compose the Empty parts directly.

No data or no match

“Nothing exists yet” and “nothing matches these filters” are different states. A list narrowed to nothing by the user’s filters or search should say so, and offer to clear them.

No alerts match these filters
Try a wider time range or remove a filter.
<ListEmptyState
  icon={SearchXIcon}
  title="No alerts match these filters"
  description="Try a wider time range or remove a filter."
  action={
    <Button variant="outline" size="sm">
      <FilterXIcon data-icon="inline-start" />
      Clear filters
    </Button>
  }
/>

In a card

In a chart or summary card, keep the card header and put the empty state in CardContent. A one-line title is usually enough there. In a table, render it in a single row that spans every column, as in the Table example.

Most targeted assets

Last 7 days
No attacks in this period
<Card className="w-full max-w-sm">
  <CardHeader>
    <CardTitle>Most targeted assets</CardTitle>
    <CardDescription>Last 7 days</CardDescription>
  </CardHeader>
  <CardContent>
    <ListEmptyState
      icon={ChartNoAxesColumnIcon}
      title="No attacks in this period"
    />
  </CardContent>
</Card>

Accessibility

  • The title is text, not a heading, so the page outline does not change when the list empties.
  • The icon is decorative. Replace the default inbox glyph through icon when another one fits the content better, but never rely on it to carry the message.

API reference

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

ListEmptyState

ListEmptyState is the "nothing to show" state of a list, a table body, a chart card or a sheet section. It is for a request that succeeded and came back empty; a request that failed renders ListErrorState instead.

PropTypeDefault
actionReactNode

The one thing the user can do from here: clear the filters, create the first item. Omit when there is nothing to do but wait for data.

-
descriptionstring

Already-translated second line. Omit for a one-line state.

-
iconLucideIcon

Replaces the default inbox glyph.

-
title*string

Already-translated title, for example "No alerts yet".

-