EmptyState
EmptyState gives an otherwise blank view a clear purpose. Use it to explain
what is absent, whether that result is expected, and what the user can do next.
It is most useful for first-use, no-result, and cleared-content states where an
empty surface would leave the user guessing.
Example
use fission::prelude::*;
let empty_projects: Widget = EmptyState {
icon: Some(Icon::svg(material::file::create_new_folder::round()).into()),
title: "No projects yet".into(),
description: Some("Create a project to organise your team's work.".into()),
action: Some(
Button {
variant: ButtonVariant::Primary,
child: Some(Text::new("Create project").into()),
on_press: Some(create_project),
..Default::default()
}
.into(),
),
}
.into();
Keep the action specific to the empty condition. A search with no matches might
offer “Clear filters”; a first-use state might offer “Create project”. Omit the
action when the message is sufficient.
Anatomy and layout
The widget has four regions:
an optional icon or illustration;
an optional description; and
an optional action widget.
The icon, title, and description form one compact header group. The action sits
in a separate region below it, so the message remains readable even when the
action has a larger touch target.
EmptyState fills the available parent width while the message header is
bounded to 384 layout points by the default recipe. The surface uses active
spacing, minimum height, border, corner-radius, color, and typography tokens.
A base surface recipe is composed with the theme's narrow surface override
when the viewport is below its configured breakpoint. The built-in packages
therefore use a 160-point minimum normally and a 128-point minimum below 640
points without requiring a second widget tree or an application-owned height.
A directly supplied Icon receives the recipe's icon size and color when the
icon has not set those values explicitly; illustrations and other retained
widgets keep their own presentation. The title uses a medium weight; the
description uses secondary text color and relaxed line height. Both are
center-aligned.
Field reference
| | | |
|---|
| | Optional visual that reinforces the state. | An unstyled Icon inherits the empty-state icon size and color; explicit icon styling and other retained widgets are preserved. |
| | Concise explanation of what is absent. | Required. Make it understandable without the description. |
| | Supporting context or guidance. | Omit it when the title and action already explain the state. |
| | The smallest useful next action. | Usually a Button; the supplied widget owns its own semantics and interaction. |
Semantics and interaction
EmptyState is presentational. It does not add a live-region role, move focus,
or dispatch an action by itself. Text remains available in the normal semantic
tree, while any supplied action retains its own button, link, or custom
semantics. When the state replaces a previously focused result, manage focus in
the surrounding screen according to that workflow instead of making every empty
state announce or capture focus automatically.
Responsive, target, and motion behavior
The panel shrinks with a narrower parent because its width is 100%. The active
design system owns the narrow breakpoint and only overrides fields it needs;
all unspecified surface properties continue to come from the base recipe. The
header and action recipes can bound their readable content independently. Its
parent still needs to provide sensible horizontal room; test long translations,
increased text scale, and compact screens so the action does not crowd the
message. If several actions are genuinely required, compose a responsive action
group as the action widget rather than widening the empty-state API.
The same presentation can lower to native, Web, Terminal, Static site, and SSR
output. EmptyState registers no motion itself. Any motion composed around its
content or action still follows the global Env::motion_preference, so the
widget does not need its own preference branch. Controls supplied in action
require an interactive target or browser island to dispatch reducers.
Production checklist
Distinguish an expected empty state from loading and error states.
Make the title state the condition, and use the description for useful
context rather than filler.
Offer one clear recovery or creation action when one exists.
Verify the panel at the narrowest supported width and with long translated
copy.
Preserve the supplied action's semantic name and keyboard behavior.