Give empty lists, first-run screens, and errors a clear next step with media, a title, supporting text, and actions.
No Projects Yet
You haven't created any projects yet. Get started by creating your first project.
tsx
import { Button } from "@/components/ui/button"import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle,} from "@/components/ui/empty"function FolderIcon(props: React.SVGProps<SVGSVGElement>) { return ( <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" {...props}> <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" /> <path d="M12 10v6" /> <path d="M9 13h6" /> </svg> )}function ArrowUpRightIcon(props: React.SVGProps<SVGSVGElement>) { return ( <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" {...props}> <path d="M7 7h10v10" /> <path d="M7 17 17 7" /> </svg> )}export function Example() { return ( <Empty> <EmptyHeader> <EmptyMedia variant="icon"> <FolderIcon /> </EmptyMedia> <EmptyTitle>No Projects Yet</EmptyTitle> <EmptyDescription> You haven't created any projects yet. Get started by creating your first project. </EmptyDescription> </EmptyHeader> <EmptyContent> <div className="flex gap-2"> <Button>Create Project</Button> <Button variant="secondary">Import Project</Button> </div> <Button variant="link" className="text-muted-foreground"> Learn More <ArrowUpRightIcon className="size-3.5" /> </Button> </EmptyContent> </Empty> )}Installation
npx @arctis-sh/@arctis-sh/ui@latest add emptyUsage
import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle,} from "@/components/ui/empty"<Empty> <EmptyHeader> <EmptyMedia variant="icon"> <Icon /> </EmptyMedia> <EmptyTitle>No projects yet</EmptyTitle> <EmptyDescription>Create one to get started.</EmptyDescription> </EmptyHeader> <EmptyContent> <Button>New project</Button> </EmptyContent></Empty>Composition
Empty ├── EmptyHeader │ ├── EmptyMedia │ ├── EmptyTitle │ └── EmptyDescription └── EmptyContent
Outline
Add a border for a more defined empty state.
Cloud Storage Empty
Upload files to your cloud storage to access them anywhere.
tsx
import { Button } from "@/components/ui/button"import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle,} from "@/components/ui/empty"function CloudIcon(props: React.SVGProps<SVGSVGElement>) { return ( <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" {...props}> <path d="M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z" /> </svg> )}export function Example() { return ( <Empty className="border border-dashed border-border"> <EmptyHeader> <EmptyMedia variant="icon"> <CloudIcon /> </EmptyMedia> <EmptyTitle>Cloud Storage Empty</EmptyTitle> <EmptyDescription> Upload files to your cloud storage to access them anywhere. </EmptyDescription> </EmptyHeader> <EmptyContent> <Button variant="secondary">Upload Files</Button> </EmptyContent> </Empty> )}Background
Add a background color or gradient directly to Empty.
No Notifications
You're all caught up. New notifications will appear here.
tsx
import { Button } from "@/components/ui/button"import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle,} from "@/components/ui/empty"function BellIcon(props: React.SVGProps<SVGSVGElement>) { return ( <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" {...props}> <path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9" /> <path d="M10.3 21a1.94 1.94 0 0 0 3.4 0" /> </svg> )}function RefreshIcon(props: React.SVGProps<SVGSVGElement>) { return ( <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" {...props}> <path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8" /> <path d="M21 3v5h-5" /> <path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16" /> <path d="M8 16H3v5" /> </svg> )}export function Example() { return ( <Empty className="rounded-none bg-muted"> <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="secondary"> <RefreshIcon className="size-3.5" /> Refresh </Button> </EmptyContent> </Empty> )}Avatar
Place an avatar inside EmptyMedia.
User Offline
This user is currently offline. You can leave a message to notify them or try again later.
tsx
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 Example() { return ( <Empty> <EmptyHeader> <EmptyMedia> <Avatar size="lg"> <AvatarImage src="/assets/brand/demos/avatars/avatar-6.png" alt="Lucia Reyes" /> <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 variant="secondary">Leave Message</Button> </EmptyContent> </Empty> )}Avatar Group
Place AvatarGroup inside EmptyMedia.
No Team Members
Invite your team to collaborate on this project.
tsx
import { Avatar, AvatarFallback, AvatarGroup, AvatarImage,} from "@/components/ui/avatar"import { Button } from "@/components/ui/button"import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle,} from "@/components/ui/empty"function PlusIcon(props: React.SVGProps<SVGSVGElement>) { return ( <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" {...props}> <path d="M5 12h14" /> <path d="M12 5v14" /> </svg> )}export function Example() { return ( <Empty> <EmptyHeader> <EmptyMedia> <AvatarGroup> <Avatar> <AvatarImage src="/assets/brand/demos/avatars/avatar-1.png" alt="Mina Cho" /> <AvatarFallback>MC</AvatarFallback> </Avatar> <Avatar> <AvatarFallback>LR</AvatarFallback> </Avatar> <Avatar> <AvatarFallback>EF</AvatarFallback> </Avatar> </AvatarGroup> </EmptyMedia> <EmptyTitle>No Team Members</EmptyTitle> <EmptyDescription> Invite your team to collaborate on this project. </EmptyDescription> </EmptyHeader> <EmptyContent> <Button> <PlusIcon className="size-3.5" /> Invite Members </Button> </EmptyContent> </Empty> )}Input Group
Place InputGroup inside EmptyContent when the next step needs input.
404 - Not Found
The page you're looking for doesn't exist. Try searching for what you need below.
Need help? Contact support
tsx
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"function SearchIcon(props: React.SVGProps<SVGSVGElement>) { return ( <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" {...props}> <circle cx="11" cy="11" r="8" /> <path d="m21 21-4.3-4.3" /> </svg> )}export function Example() { return ( <Empty> <EmptyHeader> <EmptyTitle>404 - Not Found</EmptyTitle> <EmptyDescription> The page you're looking for doesn't exist. Try searching for what you need below. </EmptyDescription> </EmptyHeader> <EmptyContent> <InputGroup variant="filled" className="w-full max-w-xs"> <InputGroupInput placeholder="Search..." /> <InputGroupAddon> <SearchIcon /> </InputGroupAddon> <InputGroupAddon align="inline-end"> <Kbd>/</Kbd> </InputGroupAddon> </InputGroup> <EmptyDescription> Need help? <a href="#">Contact support</a> </EmptyDescription> </EmptyContent> </Empty> )}API Reference
Empty
| Prop | Type | Default |
|---|---|---|
| className | string | — |
<Empty> <EmptyHeader /> <EmptyContent /></Empty>EmptyHeader
| Prop | Type | Default |
|---|---|---|
| className | string | — |
<EmptyHeader> <EmptyMedia /> <EmptyTitle /> <EmptyDescription /></EmptyHeader>EmptyMedia
| Prop | Type | Default |
|---|---|---|
| variant | "default" | "icon" | "default" |
| className | string | — |
<EmptyMedia variant="icon"> <Icon /></EmptyMedia><EmptyMedia> <Avatar> <AvatarFallback>AR</AvatarFallback> </Avatar></EmptyMedia>EmptyTitle
| Prop | Type | Default |
|---|---|---|
| className | string | — |
<EmptyTitle>No projects yet</EmptyTitle>EmptyDescription
| Prop | Type | Default |
|---|---|---|
| className | string | — |
<EmptyDescription>Nothing to show here yet.</EmptyDescription>EmptyContent
| Prop | Type | Default |
|---|---|---|
| className | string | — |
<EmptyContent> <Button>New project</Button></EmptyContent>