Skip to content

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.

React
tsx
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>}
/>;
dart
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

PropTypeDefaultDescription
iconReactNodeThe glyph or drawing above the words. Sized off size
titleReactNodeThe one line that says what is not here
descriptionReactNodeWhat to do about it. One or two sentences, never a paragraph
actionsReactNodeThe 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
PropTypeDefaultDescription
iconWidget?The glyph or drawing above the words. Sized off size
titleWidget?The one line that says what is not here
descriptionWidget?What to do about it. One or two sentences, never a paragraph
actionsList<Widget>[]The way out — usually one PlButton
childWidget?Anything else that belongs between the description and the actions
sizesharedPlassSizePlassSize.mdGlyph, type scale and the space around it
colorsharedPlassColorPlassColor.secondaryThe family the glyph takes. secondary is nothing yet, danger is something went wrong, success is you are done
densitysharedPlassDensityPlassDensity.standardThe 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
dangerSomething has
successYou are done, which is the "your order is confirmed" screen, without a second component
React

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.

React

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; pass render on a PlTypography above 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.

Released under the MIT License