Github

Empty

Display an empty state with media, text, and actions.

No Projects Yet
You haven't created any projects yet. Get started by creating your first project.
Learn More
import { ArrowUpRightIcon, FolderCode } from "lucide-react";import { Button, buttonVariants } from "@/components/ui/button";import {	Empty,	EmptyContent,	EmptyDescription,	EmptyHeader,	EmptyMedia,	EmptyTitle,} from "@/components/ui/empty";
export function EmptyDemo() {	return (		<Empty>			<EmptyHeader>				<EmptyMedia variant="icon">					<FolderCode />				</EmptyMedia>				<EmptyTitle>No Projects Yet</EmptyTitle>				<EmptyDescription>					You haven&apos;t created any projects yet. Get started by creating					your first project.				</EmptyDescription>			</EmptyHeader>			<EmptyContent className="flex-row justify-center gap-2">				<Button>Create Project</Button>				<Button variant="outline">Import Project</Button>			</EmptyContent>			<a className={buttonVariants({ variant: "link", size: "sm" })} href="#">				Learn More <ArrowUpRightIcon data-icon="inline-end" />			</a>		</Empty>	);}

Installation

pnpm dlx shadcn@latest add @herocn/empty

Usage

import {  Empty,  EmptyContent,  EmptyDescription,  EmptyHeader,  EmptyMedia,  EmptyTitle,} from "@/components/ui/empty"
<Empty>  <EmptyHeader>    <EmptyMedia variant="icon">      <Icon />    </EmptyMedia>    <EmptyTitle>No data</EmptyTitle>    <EmptyDescription>No data found</EmptyDescription>  </EmptyHeader>  <EmptyContent>    <Button>Add data</Button>  </EmptyContent></Empty>

Composition

Use the following composition to build an Empty state:

Empty├── EmptyHeader│   ├── EmptyMedia│   ├── EmptyTitle│   └── EmptyDescription└── EmptyContent

Examples

Outline

Use a dashed border to make an outlined empty state.

Cloud Storage Empty
Upload files to your cloud storage to access them anywhere.
import { Cloud } from "lucide-react";
import { Button } from "@/components/ui/button";import {	Empty,	EmptyContent,	EmptyDescription,	EmptyHeader,	EmptyMedia,	EmptyTitle,} from "@/components/ui/empty";
export function EmptyOutline() {	return (		<Empty className="border border-dashed">			<EmptyHeader>				<EmptyMedia variant="icon">					<Cloud />				</EmptyMedia>				<EmptyTitle>Cloud Storage Empty</EmptyTitle>				<EmptyDescription>					Upload files to your cloud storage to access them anywhere.				</EmptyDescription>			</EmptyHeader>			<EmptyContent>				<Button variant="outline" size="sm">					Upload Files				</Button>			</EmptyContent>		</Empty>	);}

Background

Add a muted background for low-contrast states.

No Notifications
You're all caught up. New notifications will appear here.
import { Bell, RefreshCcwIcon } from "lucide-react";
import { Button } from "@/components/ui/button";import {	Empty,	EmptyContent,	EmptyDescription,	EmptyHeader,	EmptyMedia,	EmptyTitle,} from "@/components/ui/empty";
export function EmptyBackground() {	return (		<Empty className="h-full bg-muted/30">			<EmptyHeader>				<EmptyMedia variant="icon">					<Bell />				</EmptyMedia>				<EmptyTitle>No Notifications</EmptyTitle>				<EmptyDescription className="max-w-xs text-pretty">					You&apos;re all caught up. New notifications will appear here.				</EmptyDescription>			</EmptyHeader>			<EmptyContent>				<Button variant="outline">					<RefreshCcwIcon data-icon="inline-start" />					Refresh				</Button>			</EmptyContent>		</Empty>	);}

Avatar

Use EmptyMedia to render an avatar-based empty state.

LR
User Offline
This user is currently offline. You can leave a message to notify them or try again later.
import {	Avatar,	AvatarFallback,	AvatarImage,} from "@/components/ui/avatar";import { Button } from "@/components/ui/button";import {	Empty,	EmptyContent,	EmptyDescription,	EmptyHeader,	EmptyMedia,	EmptyTitle,} from "@/components/ui/empty";
export function EmptyAvatar() {	return (		<Empty>			<EmptyHeader>				<EmptyMedia variant="default">					<Avatar className="size-12">						<AvatarImage src="https://github.com/Maqed.png" />						<AvatarFallback>LR</AvatarFallback>					</Avatar>				</EmptyMedia>				<EmptyTitle>User Offline</EmptyTitle>				<EmptyDescription>					This user is currently offline. You can leave a message to notify them					or try again later.				</EmptyDescription>			</EmptyHeader>			<EmptyContent>				<Button size="sm">Leave Message</Button>			</EmptyContent>		</Empty>	);}

Avatar Group

Show a group of avatars to indicate team or collaborator context.

MqdCNER
No Team Members
Invite your team to collaborate on this project.
import { PlusIcon } from "lucide-react";
import {	Avatar,	AvatarFallback,	AvatarImage,} from "@/components/ui/avatar";import { Button } from "@/components/ui/button";import {	Empty,	EmptyContent,	EmptyDescription,	EmptyHeader,	EmptyMedia,	EmptyTitle,} from "@/components/ui/empty";
export function EmptyAvatarGroup() {	return (		<Empty>			<EmptyHeader>				<EmptyMedia>					<div className="flex -space-x-2 *:data-[slot=avatar]:size-12 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background">						<Avatar>							<AvatarImage src="https://github.com/Maqed.png" alt="@0xMaqed" />							<AvatarFallback>Mqd</AvatarFallback>						</Avatar>						<Avatar>							<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />							<AvatarFallback>CN</AvatarFallback>						</Avatar>						<Avatar>							<AvatarImage								src="https://github.com/evilrabbit.png"								alt="@evilrabbit"							/>							<AvatarFallback>ER</AvatarFallback>						</Avatar>					</div>				</EmptyMedia>				<EmptyTitle>No Team Members</EmptyTitle>				<EmptyDescription>					Invite your team to collaborate on this project.				</EmptyDescription>			</EmptyHeader>			<EmptyContent>				<Button size="sm">					<PlusIcon data-icon="inline-start" />					Invite Members				</Button>			</EmptyContent>		</Empty>	);}

Input Group

Place interactive search or filter controls in EmptyContent.

404 - Not Found
The page you're looking for doesn't exist. Try searching for what you need below.
/
Need help? Contact support
import { SearchIcon } from "lucide-react";
import {	Empty,	EmptyContent,	EmptyDescription,	EmptyHeader,	EmptyTitle,} from "@/components/ui/empty";import {	InputGroup,	InputGroupAddon,	InputGroupInput,} from "@/components/ui/input-group";import { Kbd } from "@/components/ui/kbd";
export function EmptyInputGroup() {	return (		<Empty>			<EmptyHeader>				<EmptyTitle>404 - Not Found</EmptyTitle>				<EmptyDescription>					The page you&apos;re looking for doesn&apos;t exist. Try searching for					what you need below.				</EmptyDescription>			</EmptyHeader>			<EmptyContent>				<InputGroup className="sm:w-3/4">					<InputGroupInput placeholder="Try searching for pages..." />					<InputGroupAddon>						<SearchIcon />					</InputGroupAddon>					<InputGroupAddon align="inline-end">						<Kbd>/</Kbd>					</InputGroupAddon>				</InputGroup>				<EmptyDescription>					Need help? <a href="#">Contact support</a>				</EmptyDescription>			</EmptyContent>		</Empty>	);}

RTL

لا توجد مشاريع بعد
لم تقم بإنشاء أي مشاريع بعد. ابدأ بإنشاء مشروعك الأول.
تعرف على المزيد
"use client";
import { ArrowUpRightIcon, FolderCode } from "lucide-react";
import {	type Translations,	useTranslation,} from "@/components/language-selector";import { Button } from "@/components/ui/button";import {	Empty,	EmptyContent,	EmptyDescription,	EmptyHeader,	EmptyMedia,	EmptyTitle,} from "@/components/ui/empty";
const translations: Translations = {	en: {		dir: "ltr",		values: {			title: "No Projects Yet",			description:				"You haven't created any projects yet. Get started by creating your first project.",			createProject: "Create Project",			importProject: "Import Project",			learnMore: "Learn More",		},	},	ar: {		dir: "rtl",		values: {			title: "لا توجد مشاريع بعد",			description: "لم تقم بإنشاء أي مشاريع بعد. ابدأ بإنشاء مشروعك الأول.",			createProject: "إنشاء مشروع",			importProject: "استيراد مشروع",			learnMore: "تعرف على المزيد",		},	},	he: {		dir: "rtl",		values: {			title: "אין פרויקטים עדיין",			description:				"עדיין לא יצרת פרויקטים. התחל על ידי יצירת הפרויקט הראשון שלך.",			createProject: "צור פרויקט",			importProject: "ייבא פרויקט",			learnMore: "למד עוד",		},	},};
export function EmptyRtl() {	const { dir, language, t } = useTranslation(translations, "ar");
	return (		<div lang={language} dir={dir}>			<Empty>				<EmptyHeader>					<EmptyMedia variant="icon">						<FolderCode />					</EmptyMedia>					<EmptyTitle>{t.title}</EmptyTitle>					<EmptyDescription>{t.description}</EmptyDescription>				</EmptyHeader>				<EmptyContent className="flex-row justify-center gap-2">					<Button>{t.createProject}</Button>					<Button variant="outline">{t.importProject}</Button>				</EmptyContent>				<Button					variant="link"					render={<a href="#" />}					className="text-muted-foreground"					size="sm"					nativeButton={false}				>					{t.learnMore}					<ArrowUpRightIcon className="rtl:rotate-270" data-icon="inline-end" />				</Button>			</Empty>		</div>	);}

API Reference

Empty

The root container for the empty state.

PropTypeDefault
classNamestring
—

EmptyHeader

Wraps the media, title, and description.

PropTypeDefault
classNamestring
—

EmptyMedia

Displays an icon, image, avatar, or any custom media.

PropTypeDefault
variant"default" | "icon"
"default"
classNamestring
—

EmptyTitle

The primary heading for the empty state.

PropTypeDefault
classNamestring
—

EmptyDescription

Secondary text that explains the empty state.

PropTypeDefault
classNamestring
—

EmptyContent

Action area for buttons, inputs, or links.

PropTypeDefault
classNamestring
—