Eight contextual empty-state patterns. Each one is shown inside the surface it belongs to
(a card, a list, a sidebar) so the empty state never reads as a broken page. Every empty state has
a clear primary action — onboarding, not just absence.
Usage rules
1. Anatomy
An empty state has up to 5 parts, in order:
Glyph — small (48×48), icon-based. Use the icon that matches the surface's domain ("inbox" for notifications, "list" for orders), not a generic "empty box."
Title — what's empty, written warmly. "No positions yet", not "List is empty".
Body — one sentence: why it's empty + what would fill it.
Primary action — the verb that fills it. "Place your first trade", "Invite teammates."
Secondary path (optional) — "Learn more" link, or alternate filter to expand the result set.
2. First-time vs. recurring empty
Type
Tone
Action density
First-time — user has never had data here
Onboarding. Encouraging. Hint at what good looks like ("Place 5 trades to unlock your first achievement").
Up to 2 actions + a 3-bullet hint list
Recurring — user previously had data, now doesn't
Calm. Just state what's there. "All caught up".
1 action max, often none
Filtered — there is data, the user filtered it out
Helpful. Suggest broadening the filter.
"Clear filters" + "Adjust" button
3. Place inside the surface, not in place of the page
An empty positions list still renders the surface chrome (title bar, filter buttons, "+ New" CTA). The empty state lives inside the list area where rows would be. Replacing the entire page would lose context and disorient the user.
4. Glyph choices
Surface domain — wallet for balance, trophy for achievements, mail for messages, list for orders
Brand-tinted when the empty state is a good state ("All caught up") — uses --brand-primary-faint + --brand-primary
Neutral when the empty state is just an absence — uses --surface-2 + --muted
5. Voice rules
✓ "Place your first trade" — verb the user can act on
✗ "Empty list" — describes the data structure, not the user's situation
✓ "We'll notify you here when activity matters" — sets expectation
✗ "There is no data to display" — passive, system-centric
6. Don't
❌ Don't use the same generic "Nothing here yet" copy on every surface — the body line should be specific to this surface
❌ Don't include illustrations — the icon glyph + text is enough; saves bandwidth and avoids the "stock empty-box" cliché
❌ Don't show a primary action that requires leaving the page — keep the action local where possible
❌ Don't show empty states during loading — show a skeleton; the empty state appears only after the load resolves with zero results