EmptyState macrolite
A centred icon, title and explanation for an empty list, with an optional action.
createSurface + updateComponents, A2UI v0.9.
[
{
"version": "v0.9",
"createSurface": {
"surfaceId": "preview",
"catalogId": "https://ui.exponential.at/catalogs/core/v1"
}
},
{
"version": "v0.9",
"updateComponents": {
"surfaceId": "preview",
"components": [
{
"id": "root",
"component": "Stack",
"direction": "vertical",
"align": "stretch",
"children": [
"example"
]
},
{
"id": "example",
"component": "EmptyState",
"icon": "nav-inbox",
"title": "No notifications",
"description": "You are all caught up."
}
]
}
}
]This surface through a MemoryTransport. Install and transports: React guide.
This surface through a MemoryTransport. Install and transports: SwiftUI guide.
This surface through a MemoryTransport. Install and transports: Compose guide.
This surface through a MemoryTransport. Install and transports: gpui guide.




View exponential-ui-empty-state, painted by each native renderer.
| Prop | Type | Default | Description |
|---|---|---|---|
iconrequired | icon | – | The large glyph. |
titlerequired | string | – | What is empty. |
description | string | – | Why, or what to do next. |
actionLabel | string | – | A button label; pressing it fires press. |
| Name | Kind |
|---|---|
on.press | event: runs an action |
- Role
status- Semantics
- status; the action = button
| Keys | Action |
|---|---|
| – | Enter, Space on the action |
- Recipe parts
EmptyState/rootEmptyState/iconEmptyState/titleEmptyState/descriptionEmptyState/action- Keyed by
:hover:pressed:focus:disabled:checked:open:selected:invalid:dragover
Empty state
What a PAGE says when it has nothing: the 48px icon disc, one semibold title, one muted sentence that TEACHES the next step rather than restating the emptiness, and an optional actions slot under it — all on a centred column of at most 28rem.
More
Never a bare "No results". Its in-list sibling is `ListEmpty` (same file, its own entry below): one muted line inside a list that filtered down to nothing, where a teaching block would be wrong. The third of them is `EmptyCta` (EXP-962, next entry): the dashed box that STARTS the list, where the empty state itself is the button.
InboxView.emptyStateapps/ios/Exponential/UI/Inbox/InboxView.swiftevery screen rolls its own private empty state (inbox, reviews, actions, my issues); there is no shared symbol
EmptyStateapps/android/app/src/main/java/com/exponential/app/ui/components/Scaffolding.kta bare 28dp tinted glyph instead of the 48 disc, and its parameters are message/detail rather than title/description
controls::feedback::empty_stateapps/desktop/crates/exponential-ui-gpui/src/controls/feedback.rsEmpty call to action
EXP-962: the third empty, and the only one that is a BUTTON.
More
A dashed, full-width box standing exactly where the first row will go — a 16px glyph, one title line, one muted sentence under it, the row wash and full-strength text on hover. Dashed because it is a placeholder for the row it invites; clickable because the shortest path to that row is the box itself. `EmptyState` teaches a PAGE with nothing on it, `ListEmpty` reports a list that filtered down to nothing, and this one STARTS a list: the actions panel's "describe one" nudge is the call site it was cut from.
EmptyCtapackages/ui/src/empty-state.tsxEmptyState and ListEmpty are the other two, in the same file
the creator run needs a device: ActionsListView.emptyState is a read-only page empty instead
same: ActionsScreen's ActionsEmptyState reads, it does not invite — creation lives on web or desktop
ActionsView::render_nudgeapps/desktop/crates/ui/src/actions_view.rsthe same dashed strip under the actions list, opening the creator run
In-list empty line
The compact sibling of the empty state: one muted centred line INSIDE a list that filtered down to nothing, exactly the line `CommandEmpty` draws, for the lists that have no Command around them.
More
It is deliberately not the teaching block — a search that matched nothing needs a different QUERY, not a next step, and a 48px icon disc under a search field reads as a page having gone wrong.
Text("No emoji found")apps/ios/Exponential/UI/Markdown/EmojiPickerSheet.swiftevery list inlines its own Text: there is no shared line, and DeviceLogins.emptyLine is a private third copy
ChangesEmptyRowapps/android/app/src/main/java/com/exponential/app/ui/work/GuideSectionDiff.ktprivate to the Guide section page; the emoji sheet writes its own line, and EmptyState (Scaffolding.kt) is page-sized
pickers::empty_picker_rowapps/desktop/crates/ui/src/pickers.rsthe CommandEmpty row every picker shares; controls::empty_state is the page-sized counterpart