A centered placeholder for empty views — no results, first run, a cleared list.

Last updated

No messages yet

When someone sends you a message, it'll show up here.

Show code
<EmptyState title="No messages yet" description="When someone sends you a message, it'll show up here.">
<Inbox slot="icon" />
<Button slot="actions" size="small">Compose</Button>
</EmptyState>

Add

npx @ava-ui/apogee add empty-state

No Apogee dependencies. Commonly composed with Button in the actions slot and a @lucide/astro icon in the icon slot.

Usage

---
import EmptyState from '@/components/apogee/EmptyState/EmptyState.astro'
---
<EmptyState title="No results" description="Try a different search." />

Anatomy

  • icon slot (optional) — a leading glyph above the title. A bare SVG is sized by size ([&>svg]); a FeaturedIcon keeps its own size. The pattern decoration is drawn behind this slot.
  • Title — required, always rendered.
  • Description — optional, rendered under the title when passed.
  • actions slot (optional) — buttons or links, wrapped and centered below the text.
<EmptyState title="No projects" description="Create your first project to get started.">
  <FolderOpen slot="icon" />
  <Button slot="actions" size="small">New project</Button>
  <Button slot="actions" variant="ghost" color="neutral" size="small">Import</Button>
</EmptyState>

API

@composable — exposed to Content Editors in AVA. Any other attribute passes through to the root <div>.

Prop Type Default Description
title string — Required. The primary message.
description string — Optional supporting line, shown under the title.
as 'p' | 'h2' | 'h3' 'p' Element for the title; use a heading when the empty state is the page’s only content.
variant 'bordered' | 'plain' 'bordered' plain drops the dashed box, for use inside a card, a table body or a full page.
size 'small' | 'medium' | 'large' 'medium' Scales the icon, text and padding.
pattern 'none' | 'rings' | 'grid' 'none' A faint decoration behind the icon, drawn with the border token under a radial fade.
class string — Extra classes on the root, merged last.

Variants

Every size:

No results

Try other filters.

No results

Try other filters.

No results

Try other filters.

Show code
<EmptyState size="small" title="No results" description="…"><SearchX slot="icon" /></EmptyState>
<EmptyState size="medium" title="No results" description="…"><SearchX slot="icon" /></EmptyState>
<EmptyState size="large" title="No results" description="…"><SearchX slot="icon" /></EmptyState>

plain inside a card, where the dashed box would be a second frame:

No members yet

Invite someone to get started.

Show code
<Card padding="none">
<EmptyState variant="plain" title="No members yet" description="Invite someone to get started.">
  <Users slot="icon" />
  <Button slot="actions" size="small">Invite</Button>
</EmptyState>
</Card>

Every pattern, with a FeaturedIcon in the slot:

No projects

Create your first project to get started.

No projects

Create your first project to get started.

Show code
<EmptyState pattern="rings" title="No projects" description="…">
<FeaturedIcon slot="icon" theme="outline" color="neutral"><FolderOpen /></FeaturedIcon>
</EmptyState>
<EmptyState pattern="grid" title="No projects" description="…">
<FeaturedIcon slot="icon" color="primary"><FolderOpen /></FeaturedIcon>
</EmptyState>

A full page with a heading as the title:

Your inbox is empty

New messages land here. Nothing needs your attention right now.

Show code
<EmptyState as="h2" variant="plain" size="large" title="Your inbox is empty" description="…" />

States

  • Static: no interactive states of its own. Buttons in actions keep their own hover, focus and disabled states.
  • With or without actions: leave the slot empty when the user has nothing to do next.

Examples

Title only, no icon or actions:

Nothing here yet

Show code
<EmptyState title="Nothing here yet" />

No results after a search or filter:

No results found

Try adjusting your filters.

Show code
<EmptyState title="No results found" description="Try adjusting your filters.">
<SearchX slot="icon" />
</EmptyState>

Accessibility

Native semantics, no extra ARIA needed — a heading-less block of text and optional interactive children (icon is aria-hidden by convention if decorative; pass aria-hidden="true" on the icon yourself, since the component doesn’t add it). Any Button/link placed in actions keeps its own keyboard behaviour.

Tokens

Token Used for
--border-neutral Dashed border around the block, and the pattern lines
--foreground-neutral Title text
--foreground-neutral-faded Icon colour and description text
--radius-lg Corner radius

Do / Don’t

  • Do pair the title with a next step in actions when there’s one obvious action.
  • Do keep the description to one sentence explaining why the view is empty.
  • Don’t stack more than two actions — pick the primary path.
  • Don’t use it for error states with a retry — that reads better as an Alert.

Content

  • Title is a short noun phrase stating what’s missing (“No messages yet”, “No results found”), not an apology.
  • Description (if any) explains why or what to do next, one sentence, no ending period.
  • Action label follows Button’s content rules (verb + outcome, sentence case).