Empty

A placeholder for sections with no content yet. Composes EmptyHeader, EmptyMedia, EmptyTitle, EmptyDescription, and EmptyContent to cover everything from minimal icons to full onboarding prompts.

Anatomy

<Empty> is a centered flex column with a dashed border. EmptyHeader groups media, title, and description. EmptyContent sits below the header for action buttons or supplemental UI.

No items
Your collection is empty.
Empty (dashed border)EmptyHeaderEmptyMedia (variant="icon")EmptyTitle / EmptyDescription

Examples

Three common compositions — from minimal to full onboarding.

Icon only

Icon + text

No results
Try adjusting your search filters.

Full (with action)

No messages
Start a conversation to get going.

Media Variants

EmptyMedia supports two variants for different visual weights.

variant="icon"
Icon variant
Muted background, size-8 container, icon auto-sized to size-4.
variant="default"
Default variant
Transparent background — size the icon yourself via className.

Design Guidelines

Do

  • Include a call-to-action when possible. Tell users what to do next — "Create your first project" converts better than a static message.
  • Use an icon to reinforce context. Choose an icon related to the content type (Inbox for messages, FolderOpen for files).
  • Keep descriptions short and actionable. One sentence max — explain why it's empty and what to do about it.

Don't

  • Don't show during initial loading. Show Skeleton while data is fetching — only show Empty once the fetch confirms no results.
  • Don't use generic copy. "No data" or "Nothing here" is unhelpful. Be specific about what is missing and why.
  • Don't stack multiple empty states. One empty state per section — multiple signals either a data problem or a layout issue.

Developer Reference

Accessibility

  • Icon children inside EmptyMedia should use aria-hidden — the title and description already provide the accessible name.
  • Action buttons in EmptyContentmust have descriptive labels (avoid "Click here" or "Go").
  • Data slots: empty, empty-header, empty-icon, empty-title, empty-description, empty-content.
  • EmptyDescription supports inline links with automatic underline styling.

Usage

import {
  Empty,
  EmptyHeader,
  EmptyMedia,
  EmptyTitle,
  EmptyDescription,
  EmptyContent,
} from "@/components/ui/empty"
import { Inbox, Plus } from "lucide-react"

// Minimal
<Empty>
  <EmptyHeader>
    <EmptyMedia variant="icon">
      <Inbox aria-hidden />
    </EmptyMedia>
    <EmptyTitle>No messages</EmptyTitle>
    <EmptyDescription>Your inbox is empty.</EmptyDescription>
  </EmptyHeader>
</Empty>

// With action
<Empty>
  <EmptyHeader>
    <EmptyMedia variant="icon">
      <Inbox aria-hidden />
    </EmptyMedia>
    <EmptyTitle>No projects yet</EmptyTitle>
    <EmptyDescription>
      Create a project to get started.
    </EmptyDescription>
  </EmptyHeader>
  <EmptyContent>
    <Button>
      <Plus className="size-4" />
      New project
    </Button>
  </EmptyContent>
</Empty>