PlEmpty
The place where there is nothing, an empty list, a search that found nothing, a flow that has finished. A mark, a line, a sentence, and a way out.
import { PlEmpty } from 'plass-ui';
<PlEmpty
icon={<InboxIcon />}
title="No projects yet"
description="Start one and it will show up here."
actions={<PlButton>New project</PlButton>}
/>;import 'package:plass_ui/plass_ui.dart';
PlEmpty(
icon: const Icon(Icons.inbox),
title: const Text('No projects yet'),
description: const Text('Start one and it will show up here.'),
actions: <Widget>[PlButton(onPressed: create, child: const Text('New project'))],
);Props
| Prop | Type | Default | Description |
|---|---|---|---|
| icon | ReactNode | — | The glyph or drawing above the words. Sized off size |
| title | ReactNode | — | The one line that says what is not here |
| description | ReactNode | — | What to do about it. One or two sentences, never a paragraph |
| actions | ReactNode | — | The way out — usually one PlButton |
| sizeshared | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' | Glyph, type scale and the space around it |
| colorshared | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'secondary' | The family the glyph takes. secondary is nothing yet, danger is something went wrong, success is you are done |
| densityshared | 'default' | 'compact' | 'default' | The vertical padding, and nothing else |
| Prop | Type | Default | Description |
|---|---|---|---|
| icon | Widget? | — | The glyph or drawing above the words. Sized off size |
| title | Widget? | — | The one line that says what is not here |
| description | Widget? | — | What to do about it. One or two sentences, never a paragraph |
| actions | List<Widget> | [] | The way out — usually one PlButton |
| child | Widget? | — | Anything else that belongs between the description and the actions |
| sizeshared | PlassSize | PlassSize.md | Glyph, type scale and the space around it |
| colorshared | PlassColor | PlassColor.secondary | The family the glyph takes. secondary is nothing yet, danger is something went wrong, success is you are done |
| densityshared | PlassDensity | PlassDensity.standard | The vertical padding, and nothing else |
Every native <div> attribute passes straight through. What the shared axes mean across the library is in prop conventions.
actions is a List<Widget> laid out in a Wrap, rather than the single slot the React build takes. A Dart caller has no fragment to put two buttons in.
One component
An empty list, a search with no results, a request that failed and a flow that finished are the same arrangement (a mark, a line, a sentence, a way out), which is why they are one component. What tells them apart is color:
secondary (the default) | Nothing here yet. Nothing has gone wrong |
danger | Something has |
success | You are done, which is the "your order is confirmed" screen, without a second component |
No surface of its own
An empty state is always inside something (a card, a table, a panel), and a sheet inside a sheet is two sheets. What this decides is the arrangement and the space around it.
PlTable's empty prop takes a node, and this is the node it was waiting for.
The action
The one thing worth getting right. A screen that says "No projects" and stops is a dead end; the same screen with a "New project" button is the best moment in the whole flow to offer one. The reader is looking straight at the space the thing would go in.
If there is genuinely nothing to do (a search with no results, where the action is "type something else") say that in the description rather than inventing a button.
Accessibility
- The glyph is
aria-hidden. The title says what it says, and a reader should not be told twice. - It has no role of its own. Put
role="status"on it when the emptiness is the result of something the reader just did (clearing a filter, running a search), so the change is announced. Leave it off for a list that was empty when the page loaded, which has already been read. - The title is a
<p>rather than a heading. Where it belongs in a document's outline is the page's decision and not this component's; passrenderon aPlTypographyabove it if it needs to be one.
The glyph is wrapped in an ExcludeSemantics, and there is no role: put the empty state inside a Semantics(liveRegion: true) when the emptiness is the result of something the reader just did.