For the complete documentation index, see llms.txt. Markdown variants are available by appending .md to any URL or sending an Accept: text/markdown header. An agent skill is available at /.well-known/agent-skills/site-skill.md.
Home

Empty

A placeholder state for when content is absent — communicates context and guides the user toward the next action.

No messages yet

When you receive messages they'll appear here. Start a conversation to get going.

import { Inbox } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Empty, EmptyAction, EmptyDescription, EmptyIcon, EmptyTitle } from "@/components/ui/empty";

export const EmptyDemo = () => (
    <Empty>
      <EmptyIcon><Inbox /></EmptyIcon>
      <EmptyTitle>No messages yet</EmptyTitle>
      <EmptyDescription>When you receive messages they'll appear here. Start a conversation to get going.</EmptyDescription>
      <EmptyAction><Button>New message</Button></EmptyAction>
    </Empty>
  );

With multiple actions

Use EmptyAction with multiple buttons when there are two clear paths forward.

import { FolderOpen } from "lucide-react";
import { Button } from "@/components/ui/button";
import {
  Empty,
  EmptyAction,
  EmptyDescription,
  EmptyIcon,
  EmptyTitle,
} from "@/components/ui/empty";
 
<Empty>
  <EmptyIcon>
    <FolderOpen />
  </EmptyIcon>
  <EmptyTitle>No projects found</EmptyTitle>
  <EmptyDescription>
    Create a project to organise your work, or import an existing one.
  </EmptyDescription>
  <EmptyAction>
    <Button>Create project</Button>
    <Button variant="outline">Import</Button>
  </EmptyAction>
</Empty>

Without icon

Skip EmptyIcon when the context is already clear — for example inside a table or list where a large icon would feel heavy.

import {
  Empty,
  EmptyAction,
  EmptyDescription,
  EmptyTitle,
} from "@/components/ui/empty";
import { Button } from "@/components/ui/button";
 
<Empty className="py-8">
  <EmptyTitle>No results</EmptyTitle>
  <EmptyDescription>
    Try adjusting your filters or search terms.
  </EmptyDescription>
  <EmptyAction>
    <Button variant="outline" size="sm">Clear filters</Button>
  </EmptyAction>
</Empty>

In a table

Drop Empty directly inside a TableCell spanning all columns.

import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { Empty, EmptyDescription, EmptyTitle } from "@/components/ui/empty";
import { SearchX } from "lucide-react";
 
<Table>
  <TableHeader>
    <TableRow>
      <TableHead>Name</TableHead>
      <TableHead>Status</TableHead>
      <TableHead>Amount</TableHead>
    </TableRow>
  </TableHeader>
  <TableBody>
    <TableRow>
      <TableCell colSpan={3}>
        <Empty className="py-8">
          <EmptyIcon>
            <SearchX />
          </EmptyIcon>
          <EmptyTitle>No results</EmptyTitle>
          <EmptyDescription>Try a different search term.</EmptyDescription>
        </Empty>
      </TableCell>
    </TableRow>
  </TableBody>
</Table>

Full page

For page-level empty states, let Empty fill the available space with className="min-h-[60vh]".

import { PackageOpen } from "lucide-react";
import { Button } from "@/components/ui/button";
import {
  Empty,
  EmptyAction,
  EmptyDescription,
  EmptyIcon,
  EmptyTitle,
} from "@/components/ui/empty";
 
export default function OrdersPage() {
  return (
    <main className="container">
      <h1 className="text-2xl font-semibold">Orders</h1>
      <Empty className="min-h-[60vh]">
        <EmptyIcon>
          <PackageOpen />
        </EmptyIcon>
        <EmptyTitle>No orders yet</EmptyTitle>
        <EmptyDescription>
          Orders placed by your customers will appear here.
        </EmptyDescription>
        <EmptyAction>
          <Button>Share your store</Button>
        </EmptyAction>
      </Empty>
    </main>
  );
}

Props

Empty

PropTypeDefaultDescription
classNamestring—Override py-12 for tighter/looser contexts, or add min-h-* for full-page states

EmptyIcon

PropTypeDefaultDescription
classNamestring—Override size-14 or the background colour

Accepts any icon or image element as children. Icons without an explicit size-* class are auto-sized to size-6.

EmptyTitle

Renders as <h3>. Accepts all native h3 props.

EmptyDescription

Renders as <p> with max-w-xs text-muted-foreground. Accepts all native p props.

EmptyAction

A flex row wrapper for buttons. Pass one or two Button elements. Accepts all native div props.

Usage

import {
  Empty,
  EmptyAction,
  EmptyDescription,
  EmptyIcon,
  EmptyTitle,
} from "@/components/ui/empty";
import { Button } from "@/components/ui/button";
import { Inbox } from "lucide-react";
 
<Empty>
  <EmptyIcon>
    <Inbox />
  </EmptyIcon>
  <EmptyTitle>No messages yet</EmptyTitle>
  <EmptyDescription>
    Start a conversation to get going.
  </EmptyDescription>
  <EmptyAction>
    <Button>New message</Button>
  </EmptyAction>
</Empty>

Specs

# Mint — Empty Specs
 
## Component
- name: empty
- file: registry/mint/empty.tsx
- installs to: components/ui/empty.tsx
- dependencies: none
- registryDependencies: none
- GIN Design exclusive (not in shadcn/ui)
 
## What is it
A compound component for communicating the absence of content — used when a
list, table, or page has nothing to show. It structures an icon, title,
description, and action into a centred, vertically stacked layout. Use it
instead of a blank area whenever users need context and a clear next step.
Do not use it for loading or error states; prefer a Spinner or an alert for
those cases.
 
## Visual identity
Minimal and calm, with a soft mint tint. The icon sits in a rounded circle
using Mint's muted green wash that softens the emptiness without drawing
excessive attention. Typography is tight — semibold title with small muted
description — keeping the message focused. The gentle green tone carries
through consistently wherever Empty appears.
 
## Design tokens
--muted: oklch(0.96 0.02 155) / oklch(0.2 0.03 155)           — EmptyIcon background
--muted-foreground: oklch(0.52 0.06 155) / oklch(0.6 0.06 155) — EmptyIcon icon colour and EmptyDescription text
 
## Sub-components
- Empty            → root container; flex-col, items-center, justify-center, gap-3, py-12, text-center
- EmptyIcon        → muted circle (size-14, rounded-full, bg-muted, text-muted-foreground); auto-sizes child SVGs to size-6
- EmptyTitle       → h3; text-base font-semibold leading-none tracking-tight
- EmptyDescription → p; text-sm text-muted-foreground max-w-xs
- EmptyAction      → div; mt-1 flex flex-wrap items-center justify-center gap-2; holds 1–2 Button elements
 
## Conventions
- Default vertical padding is py-12; override with className for tighter contexts (py-8 in tables) or full-page states (min-h-[60vh])
- Skip EmptyIcon in dense contexts such as table rows where a large icon adds visual noise
- EmptyTitle should be a noun phrase naming what is missing ("No messages yet")
- EmptyDescription should be 1–2 sentences explaining why and what to do next
- EmptyAction action labels should use an action verb matching the creation flow ("New message", "Create project")
- Avoid vague filler copy ("Oops! Nothing here.") — be specific and helpful
- Sub-components expose data-slot="empty", data-slot="empty-icon", data-slot="empty-title", data-slot="empty-description", and data-slot="empty-action" for CSS targeting

Installation

GIN Design Plugin
$ npx shadcn add https://gin-design.vercel.app/empty