Installation
Theme
Mode

Feedback

Empty state

What fills the space when there’s no data — a blank list, a search with no hits, a brand-new workspace, a failed load. The counterpart to Skeleton: where Skeleton says “loading,” Empty state explains why it’s empty and offers the one next step.

$npx shadcn@latest add @orbit/empty-state

Overview

A tone-matched glyph in a soft badge, a headline, body copy, and up to two calls to action.

In a panel

No tasks yet

When you add tasks to this project they’ll show up here. Create your first one to get the board moving.

Presets

Each situation pairs a tone-matched glyph with copy and the right call to action — empty, no-results, no-members, first-run, and error.

Empty list · brand

No tasks yet

When you add tasks to this project they’ll show up here. Create your first one to get the board moving.

No results · neutral

No matching tasks

No tasks match your current filters. Try broadening the search or clearing a filter or two.

No members · accent

Just you so far

Invite teammates to collaborate on this workspace. They’ll be able to see projects you share with them.

First run · success

Welcome to Orbit

Create a project to organize your work into boards, milestones, and timelines. It only takes a minute.

Error · danger

In context

When a filtered table returns nothing, drop the no-results state into the body — header and toolbar stay so the user can adjust filters.

Tasks
Priority: UrgentSearch…
TaskStatusAssigneeEst

No matching tasks

No tasks match your current filters. Try broadening the search or clearing a filter or two.

Alignment & density

Center for full-panel moments; left-aligned and compact when the state lives inside a smaller card or sidebar. Drop the secondary action when there’s only one sensible next step.

Left · compact

Just you so far

Invite teammates to collaborate on this workspace. They’ll be able to see projects you share with them.

No secondary action

Welcome to Orbit

Create a project to organize your work into boards, milestones, and timelines. It only takes a minute.

Props

PropTypeDefaultDescription
iconReactNodeDecorative ~34px glyph shown in the soft tone badge (aria-hidden). EmptyStateGlyph ships the spec’s five artworks: tasks, search, members, rocket, error.
tone"brand" | "neutral" | "accent" | "success" | "danger""brand"Colors the glyph badge and the primary CTA via theme tokens.
titleReactNodeHeadline — rendered as a real heading.
descriptionReactNodeBody copy explaining why it’s empty.
align"center" | "left""center"Center for panels, left for smaller cards and sidebars.
size"md" | "compact""md"48/32px padding and a 62px badge, or 30/24px with a 52px badge.
primaryAction{ label, icon?, onClick? }Solid tone-colored CTA — a restyled Button (36px, 9px radius).
secondaryAction{ label, icon?, onClick? }Quiet outlined Button rendered before the primary.
actionsReactNodeCustom action slot — replaces the built-in primary/secondary buttons.
…restHTMLAttributes<HTMLDivElement>Everything else is forwarded to the root <div>, including ref.

Usage

Do

Name the reason it’s empty

“No tasks match your filters” tells the user more than a generic “Nothing here”.

Don’t

Offer a wall of actions

One primary step, maybe one secondary. More choices just stall the user.

Do

Match the tone to the cause

A first-run is welcoming; an error is calm and reassuring. The glyph and copy should reflect that.

Don’t

Reuse one state everywhere

No-results and no-data-yet need different copy — the user’s next move isn’t the same.

Keyboard & accessibility

The title is a real heading. The root announces as role=status — or role=alert for the danger tone — so late-arriving empty/error states are read out. CTAs are native focusable buttons, and the decorative glyph is aria-hidden.

Tab reaches the CTAs; the danger tone announces as an alert