Empty

Empty

A centered placeholder for states with nothing to show. Composes a media slot, title, description and an area for actions.

Playground

No documents
Upload a document or create one from a template.
title
description
media
actions
<Empty>
  <EmptyHeader>
    <EmptyMedia variant="icon">
      <FileText />
    </EmptyMedia>
    <EmptyTitle>No documents</EmptyTitle>
    <EmptyDescription>
      Upload a document or create one from a template.
    </EmptyDescription>
  </EmptyHeader>
  <EmptyContent>
    <Button size="sm">
      <Plus />
      New document
    </Button>
  </EmptyContent>
</Empty>

Preview

Stack EmptyMedia, EmptyTitle and EmptyDescription inside an EmptyHeader, then put calls to action in EmptyContent.

No documents
Upload a document or create one from a template.
<Empty>
  <EmptyHeader>
    <EmptyMedia variant="icon">
      <FileText />
    </EmptyMedia>
    <EmptyTitle>No documents</EmptyTitle>
    <EmptyDescription>
      Upload a document or create one from a template.
    </EmptyDescription>
  </EmptyHeader>
  <EmptyContent>
    <Button size="sm">
      <Plus />
      New document
    </Button>
  </EmptyContent>
</Empty>

Installation

npx shadcn@latest add https://espresso-base-ui.vercel.app/r/empty.json

Usage

import {
  Empty,
  EmptyContent,
  EmptyDescription,
  EmptyHeader,
  EmptyMedia,
  EmptyTitle,
} from "@/components/ui/empty"
<Empty>
  <EmptyHeader>
    <EmptyTitle>No projects yet</EmptyTitle>
    <EmptyDescription>
      Create your first project to get started.
    </EmptyDescription>
  </EmptyHeader>
</Empty>

Media variants

EmptyMedia takes a variant: icon renders a small muted tile that auto-sizes an svg child, while the default variant is an unstyled slot for larger artwork – illustrations, avatars or avatar groups.

Inbox is empty
New messages will appear here.
All clear
You have no pending notifications.
<EmptyMedia variant="icon">
  <Inbox />
</EmptyMedia>

<EmptyMedia>
  <div className="flex size-16 items-center justify-center rounded-full bg-muted">
    <Inbox className="size-8 text-muted-foreground" />
  </div>
</EmptyMedia>

With actions

EmptyContent centers whatever follows the header – pair a primary and a secondary button, or drop in a search input for no-results states.

No teammates yet
Invite people to collaborate on this workspace.
<Empty>
  <EmptyHeader>
    <EmptyMedia variant="icon">
      <Users />
    </EmptyMedia>
    <EmptyTitle>No teammates yet</EmptyTitle>
    <EmptyDescription>
      Invite people to collaborate on this workspace.
    </EmptyDescription>
  </EmptyHeader>
  <EmptyContent>
    <div className="flex items-center gap-2">
      <Button size="sm">
        <Plus />
        Invite
      </Button>
      <Button variant="outline" size="sm">
        Learn more
        <ArrowRight />
      </Button>
    </div>
  </EmptyContent>
</Empty>

No results

For filtered views, pair a Search icon tile with a search input in EmptyContent; links inside EmptyDescription are underlined automatically.

No results found
Try adjusting your search or filter to find what you are looking for.
<Empty>
  <EmptyHeader>
    <EmptyMedia variant="icon">
      <Search />
    </EmptyMedia>
    <EmptyTitle>No results found</EmptyTitle>
    <EmptyDescription>
      Try adjusting your search or filter to find what you are looking for.
    </EmptyDescription>
  </EmptyHeader>
  <EmptyContent>
    <InputGroup>
      <InputGroupAddon>
        <Search />
      </InputGroupAddon>
      <InputGroupInput placeholder="Search again..." />
    </InputGroup>
  </EmptyContent>
</Empty>

API reference

All parts render plain divs and accept className plus standard div props – only EmptyMedia has a variant. The root draws a dashed rounded border by default; override it with className (e.g. border-solid or border-none) to match the surrounding surface.

EmptyMedia

PropTypeDefaultDescription
variant"default" | "icon""default"icon renders a size-7 muted rounded tile that auto-sizes an svg child to size-4; default is a transparent free-form slot.
ComponentDescription
EmptyCentered flex container (data-slot="empty") with a dashed border, rounded corners and balanced text.
EmptyHeaderVertical stack for media, title and description (data-slot="empty-header").
EmptyMediaMedia slot above the title (data-slot="empty-icon"), reflecting its variant as data-variant.
EmptyTitleMedium-weight heading line (data-slot="empty-title").
EmptyDescriptionMuted supporting copy (data-slot="empty-description") with underlined links that highlight on hover.
EmptyContentCentered action area below the header (data-slot="empty-content") for buttons, inputs or custom content.

Styling hooks

Every part exposes a data-slot attribute (empty, empty-header, empty-icon, empty-title, empty-description, empty-content) and EmptyMedia also reflects data-variant – target these from CSS for app-level overrides. The component is purely presentational, so give the surrounding region an accessible name or status role if the empty state should be announced.

Search documentation

Search the component docs