EmptyState
A placeholder component displayed when a list or data area has no content. Includes an icon, title, optional description, and optional call-to-action button. Renders inside a dashed border container.
Anatomy
A centered flex column inside a dashed rounded border. Top to bottom: icon in a muted circle, bold title, muted description text, and an optional primary button.
No projects yet
Create your first project to get started.
Variants
With action
No projects yet
Create your first project to get started.
Without action
Inbox zero
You're all caught up. No new notifications.
Search empty
No results found
Try adjusting your search or filter criteria.
With CTA
No team members
Invite your colleagues to start collaborating.
Common Contexts
EmptyState adapts to many data-list scenarios by swapping the icon and copy.
All caught up
No unread notifications.
No documents
Upload your first document.
No results
Try a different search term.
Design Guidelines
Do
- Provide a clear CTA when possible. Empty states are prime opportunities to guide users to the next action.
- Use context-specific icons and copy. "No projects yet" is more helpful than a generic "Nothing here" message.
- Use for truly empty states. Show this only when a list or view has zero items — not for loading or error states.
Don't
- Don't use for error states. Network or permission errors need different messaging — use an Alert or dedicated error component.
- Don't stack multiple EmptyStates. One empty state per view; if multiple sections are empty, show a single top-level message.
- Don't write long descriptions. One sentence is enough — the user should understand the situation and what to do next immediately.
Developer Reference
Props
icon(optional, default:Inbox) — aLucideIcondisplayed in the muted circle.title(required) — bold heading shown below the icon.description(optional) — muted supporting text below the title.actionLabel(optional) — label for the primary CTA button. Button only renders if this prop is provided.onAction(optional) — click handler for the CTA button.className— applied to the outer container for sizing overrides.
Usage
import { OriginUiEmptyState } from "@/components/branding/origin-ui-empty-state"
import { FolderOpen, Inbox } from "lucide-react"
// With action button
<OriginUiEmptyState
icon={FolderOpen}
title="No projects yet"
description="Create your first project to get started."
actionLabel="New Project"
onAction={() => router.push("/projects/new")}
/>
// Without action
<OriginUiEmptyState
icon={Inbox}
title="Inbox zero"
description="You're all caught up. No new notifications."
/>