EmptyState
ImplementedEmpty/zero-state placeholder — icon slot + required title + optional description and action node. default/compact/centered/info variants. The fleet's most-consumed molecule (lists, tables, search results).
patterns/molecules/emptystate.htmlZero-state placeholder — decorative icon slot + required title + description + action node. Composes the Heading and Body atoms; ships no strings of its own.
EmptyState
Feedback molecule (Family 4 — Tier 1)
Renders a `role="status"` live region with a semantic heading (h2, or h3 in compact), an optional decorative icon, an optional description, and an action slot. Three layout variants: default / compact / centered.
No results
Try a different search term or clear your filters.
No tickets yet
Your purchased tickets will appear here.
No entries
This component supports light and dark mode.
Usage
The minimum is a localized title — never render the molecule bare (NASA Rule 7). Inside tables use variant="compact"; for hero-level empty pages use variant="centered" with an action.
import { EmptyState, Button } from '@epasslive/design-system'
// Minimum — localized title only
<EmptyState title={t('noEventsTitle')} />
// Full — icon + description + action, centered
<EmptyState
variant="centered"
icon={<CalendarIcon />}
title={t('noEventsTitle')}
description={t('noEventsDefault')}
action={<Button variant="secondary" onClick={resetFilters}>{t('clearFilters')}</Button>}
/>
// Table cells — compact via ResponsiveTable's emptyState slot
<ResponsiveTable
emptyState={<EmptyState variant="compact" title={t('empty')} />}
columns={columns}
rows={rows}
/>Props
title*stringHeading text (Heading atom — h2, or h3 in `compact`). The only required prop; also provides the accessible name via `aria-labelledby`. Never render an empty empty state (NASA Rule 7).
iconReact.ReactNodeDecorative icon rendered before the title. The wrapper span is `aria-hidden="true"` — never place a labelled live element (e.g. a Spinner with `aria-label`) in this slot; its label would be suppressed.
descriptionstringSecondary text (Body atom — `sm` in compact, `base` otherwise), wired via `aria-describedby` and clamped to `max-w-prose`.
actionReact.ReactNodeAction node (e.g. a Button) rendered in a `flex flex-wrap gap-2` row. Supply any interactive element — its accessible name and tap target are owned by that element.
variant'default' | 'compact' | 'centered'defaultLayout variant. `default`: left-aligned, `py-12`, h2. `compact`: left, `py-6`, h3, sm body — table cells and tight cards. `centered`: centered, `py-16`, h2.
ariaLabelstringDeprecated — currently a no-op. The container always renders `aria-labelledby` pointing at the title id, and `aria-labelledby` takes ARIA precedence over `aria-label`, so this value never reaches assistive tech. Source fix queued; rely on `title` until it lands.
classNamestringAdditional CSS classes merged onto the container after the variant classes (e.g. `py-8` to tighten padding inside a table cell).
idstringRoot element id. Falls back to a generated `useId`; also derives the `-title` / `-description` aria ids.
Props
EmptyState
titlestring—Heading text — required; never render an empty empty state.
iconReact.ReactNode—Decorative icon node (aria-hidden by the molecule — never place a labelled live element here).
descriptionstring—Secondary/descriptive text.
actionReact.ReactNode—Action node rendered at the end (e.g. a Button).
variantEmptyStateVariant'default'Layout variant: 'default' | 'compact' | 'centered' | 'info'.
ariaLabelstring—Currently a no-op — aria-labelledby takes precedence in the markup; a precedence fix is tracked for step 6.
classNamestring—Additional CSS classes on the status wrapper.
idstring—Stable root id; keys the title element for aria-labelledby.
<EmptyState />Accessibility
Type
1 ruleARIA
1 ruleUsage
Import
import { EmptyState } from "@epasslive/design-system"Example 1
<EmptyState title={t("empty")} description={t("emptyHint")} variant="compact" />Example 2
<EmptyState variant="centered" title={t("noResults")} icon={searchIcon} action={<Button variant="secondary">{t("reset")}</Button>} />Anti-patterns
— Do not render a bare <EmptyState /> — title is required
— Do not place a labelled live element (e.g. Spinner) in the icon slot — it is aria-hidden