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-stateOverview
A tone-matched glyph in a soft badge, a headline, body copy, and up to two calls to action.
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.
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 matching tasks
No tasks match your current filters. Try broadening the search or clearing a filter or two.
Just you so far
Invite teammates to collaborate on this workspace. They’ll be able to see projects you share with them.
Welcome to Orbit
Create a project to organize your work into boards, milestones, and timelines. It only takes a minute.
Couldn’t load tasks
Something went wrong fetching this list. Check your connection and try again — your work is safe.
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.
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.
Just you so far
Invite teammates to collaborate on this workspace. They’ll be able to see projects you share with them.
Welcome to Orbit
Create a project to organize your work into boards, milestones, and timelines. It only takes a minute.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| icon | ReactNode | — | Decorative ~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. |
| title | ReactNode | — | Headline — rendered as a real heading. |
| description | ReactNode | — | Body 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. |
| actions | ReactNode | — | Custom action slot — replaces the built-in primary/secondary buttons. |
| …rest | HTMLAttributes<HTMLDivElement> | — | Everything else is forwarded to the root <div>, including ref. |
Usage
Name the reason it’s empty
“No tasks match your filters” tells the user more than a generic “Nothing here”.
Offer a wall of actions
One primary step, maybe one secondary. More choices just stall the user.
Match the tone to the cause
A first-run is welcoming; an error is calm and reassuring. The glyph and copy should reflect that.
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.
Couldn’t load tasks
Something went wrong fetching this list. Check your connection and try again — your work is safe.