Components / Feedback

EmptyState macrolite

A centred icon, title and explanation for an empty list, with an optional action.

Children
none
Loading the renderer…
EmptyState rendered by the React renderer on Web
Web React
EmptyState rendered by the SwiftUI renderer on iOS
iOS SwiftUI
EmptyState rendered by the Compose renderer on Android
Android Compose
EmptyState rendered by the gpui renderer on Desktop
Desktop gpui

View exponential-ui-empty-state, painted by each native renderer.

PropTypeDefaultDescription
iconrequiredicon–The large glyph.
titlerequiredstring–What is empty.
descriptionstring–Why, or what to do next.
actionLabelstring–A button label; pressing it fires press.
NameKind
on.pressevent: runs an action
Role
status
Semantics
status; the action = button
KeysAction
–Enter, Space on the action
Recipe parts
EmptyState/rootEmptyState/iconEmptyState/titleEmptyState/descriptionEmptyState/action
Keyed by
:hover:pressed:focus:disabled:checked:open:selected:invalid:dragover

Themes · Write a theme

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.

iOSleftover
InboxView.emptyStateapps/ios/Exponential/UI/Inbox/InboxView.swift

every screen rolls its own private empty state (inbox, reviews, actions, my issues); there is no shared symbol

Androidleftover
EmptyStateapps/android/app/src/main/java/com/exponential/app/ui/components/Scaffolding.kt

a bare 28dp tinted glyph instead of the 48 disc, and its parameters are message/detail rather than title/description

Empty 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.

Webok
EmptyCtapackages/ui/src/empty-state.tsx

EmptyState and ListEmpty are the other two, in the same file

iOSn/a

the creator run needs a device: ActionsListView.emptyState is a read-only page empty instead

Androidn/a

same: ActionsScreen's ActionsEmptyState reads, it does not invite — creation lives on web or desktop

Desktopok
ActionsView::render_nudgeapps/desktop/crates/ui/src/actions_view.rs

the 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.

Webok
ListEmptypackages/ui/src/empty-state.tsx

EmptyState in the same file is the page-sized one

iOSleftover
Text("No emoji found")apps/ios/Exponential/UI/Markdown/EmojiPickerSheet.swift

every list inlines its own Text: there is no shared line, and DeviceLogins.emptyLine is a private third copy

Androidleftover
ChangesEmptyRowapps/android/app/src/main/java/com/exponential/app/ui/work/GuideSectionDiff.kt

private to the Guide section page; the emoji sheet writes its own line, and EmptyState (Scaffolding.kt) is page-sized

Desktopok
pickers::empty_picker_rowapps/desktop/crates/ui/src/pickers.rs

the CommandEmpty row every picker shares; controls::empty_state is the page-sized counterpart