Empty
An empty state with an icon, a message and actions.
No projects yet
You haven't created any projects. Get started by creating your first one or importing an existing project.
import { Button } from '@/components/ui/button'
import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle } from '@/components/ui/empty'
export default function EmptyDemo() {
return (
<Empty>
<EmptyHeader>
<EmptyMedia variant="icon">
<FolderIcon />
</EmptyMedia>
<EmptyTitle>No projects yet</EmptyTitle>
<EmptyDescription>
You haven't created any projects. Get started by creating your first one or importing an existing project.
</EmptyDescription>
</EmptyHeader>
<EmptyContent>
<div className="flex gap-2">
<Button>Create project</Button>
<Button variant="outline">Import project</Button>
</div>
</EmptyContent>
</Empty>
)
}
function FolderIcon() {
return (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round">
<path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" />
</svg>
)
}
Installation
pnpm dlx shadcn@latest add https://kagadmodyaa.vercel.app/r/empty.jsonNeeds a React + Tailwind project set up with shadcn. Copies the component source straight into your project, so you can edit it.
Empty imports cn() from lib/utils.ts — add it too if you don't have it yet:
import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
Usage
import { Empty, EmptyHeader, EmptyMedia, EmptyTitle, EmptyDescription, EmptyContent } from '@/components/ui/empty'
<Empty>
<EmptyHeader>
<EmptyMedia variant="icon"><InboxIcon /></EmptyMedia>
<EmptyTitle>Nothing here yet</EmptyTitle>
<EmptyDescription>Messages you receive will show up here.</EmptyDescription>
</EmptyHeader>
<EmptyContent>
<Button>Compose</Button>
</EmptyContent>
</Empty>Examples
Outlined
No notifications
You're all caught up. New notifications will appear here.
No results found
Nothing matched “flux capacitor”. Try a different search term.
import { Button } from '@/components/ui/button'
import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle } from '@/components/ui/empty'
/** A dashed outline suits an empty slot inside a page; the search variant points to a way out. */
export default function EmptyOutline() {
return (
<div className="grid w-full max-w-2xl gap-4 sm:grid-cols-2">
<Empty className="border border-dashed">
<EmptyHeader>
<EmptyMedia variant="icon">
<BellIcon />
</EmptyMedia>
<EmptyTitle>No notifications</EmptyTitle>
<EmptyDescription>You're all caught up. New notifications will appear here.</EmptyDescription>
</EmptyHeader>
<EmptyContent>
<Button variant="outline" size="sm">
Refresh
</Button>
</EmptyContent>
</Empty>
<Empty className="border border-dashed">
<EmptyHeader>
<EmptyMedia variant="icon">
<SearchIcon />
</EmptyMedia>
<EmptyTitle>No results found</EmptyTitle>
<EmptyDescription>Nothing matched “flux capacitor”. Try a different search term.</EmptyDescription>
</EmptyHeader>
<EmptyContent>
<Button variant="link" size="sm">
Clear search
</Button>
</EmptyContent>
</Empty>
</div>
)
}
function BellIcon() {
return (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round">
<path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9M10.3 21a1.94 1.94 0 0 0 3.4 0" />
</svg>
)
}
function SearchIcon() {
return (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round">
<circle cx="11" cy="11" r="8" />
<path d="m21 21-4.3-4.3" />
</svg>
)
}
API Reference
| Name | Type | Default | Description |
|---|---|---|---|
| Empty | div props | — | The centred container. Add a border or background with className. |
| EmptyMedia variant | 'default' | 'icon' | 'default' | icon puts the icon in a soft rounded square. |
| EmptyTitle / EmptyDescription | component | — | The heading and supporting text. |
| EmptyContent | div props | — | Holds the actions below the text. |