Empty state
Explains why a region is empty.
Reason
No agents yet
Create one to start a run.
emptydefault
No runs match
Clear the filter to see all.
no-results
You cannot see billing
Ask an owner for access.
no-access
Runs did not load
Retry, or check the status page.
error
Sizes
No agents yet
Create one to start a run.
defaultdefault
No agents yet
Create one to start a run.
sm
States
No agents yet
An agent answers tickets.
rest
No agents yet
An agent answers tickets.
focus-visible
Runs did not load
Check the status page.
retrying
Usage
Rules
9 rules
- Must
- Set reason to why it is empty: empty, no-results, no-access or error. Because each picks its glyph and error adds role="alert" and the failure colour, so a failed load drawn as empty tells the person to create what already exists.
- Must
- Write the search or filter back in a no-results title, in <code>, and offer to clear it. Because a bare "No results" leaves the person guessing which filter emptied the list.
- Must
- Use variant="plain" inside a Card, an ItemGroup or a table; panel only on its own. Because panel draws the white surface, and a panel inside a card's panel is a box in a box.
- Must
- Let Empty centre itself: the reason's glyph on top, then EmptyTitle, one line of EmptyDescription and EmptyContent, in one column. Because Empty draws the 40px light glyph in text-3 (32 at size="sm") and the compact rhythm, so a hand-built row or a start-aligned override breaks the one shape every empty region shares.
- Never
- Add an illustration, a second glyph or your own icon tile; pass EmptyTitle icon to change the glyph. Because the region is compact, and art pushes the one action below the fold for no information.
- Must
- Retry a failed load with EmptyRetry and a promise that rejects when it fails again. Because EmptyRetry holds its box while it runs and says "Retry 2 failed at 14:03:12", so a dead endpoint never looks like a dead button.
- Must
- Offer at most one action in EmptyContent: variant="secondary" by default, primary only when it is the only way forward. Because the region has one job, and an ink pill on every empty list makes creating things look like the page's next step.
- Should
- Keep EmptyDescription to one line: why it is empty or what the action does. Because a paragraph centred under a glyph reads as a landing page, not a region waiting for rows.
- Should
- Move focus to the first row after a successful retry. Because the Retry button that held focus is gone once the content replaces the Empty.
Accessibility
4 checks
- The title is an h3; change the tag in the installed file where the page needs another level.
- error is role="alert"; the retry's second failure speaks once through a status line.
- The glyph is decorative; the title says the reason in words.
- Description is text-2, 5.5:1 on paper; the error title is fail-text, 5.9:1.
Keyboard
2 keys
- Tab
- Moves to the action.
- Enter
- Presses it; EmptyRetry blocks repeats while pending.
Edge cases
4 edge cases
- Long query
- The code in the title breaks anywhere rather than overflowing.
- Retry fails again
- The button returns to rest and the line says which retry failed and when.
- Narrow at 390
- The column stays centred and the title and description wrap, balanced.
- Dark theme
- The panel and the words flip with the tokens.
API
5 props
reason'empty' | 'no-results' | 'no-access' | 'error'default'empty'variant'panel' | 'plain'default'panel'size'default' | 'sm'default'default'EmptyTitle iconGlazeIcon | falseEmptyRetry onRetry() => Promise<unknown>
Tokens
14 tokens
--paper- #ffffff
--line-faint- rgb(5 5 5 / 0.06)
--radius-panel- 11px
--text-1- rgb(5 5 5 / 0.80)
--text-2- rgb(5 5 5 / 0.60)
--text-3- rgb(5 5 5 / 0.45)
--fail-text- #b23c29
--type-label- 500 13px/1.35 var(--font-sans)
--type-body-sm- 400 13px/1.5 var(--font-sans)
--type-caption- 400 12px/1.35 var(--font-sans)
--measure-hint- 60ch
--space-3- 12px
--space-4- 16px
--space-6- 24px