What stands where a list or panel has nothing to show: what is missing, why, and the way forward (also called a blank slate). Reach for it for a first use, a filter that found nothing, or a queue that is clear.
import { EmptyState } from "@umriss-ui/core";
The title says what is missing, the description what would bring it, and the action is the way there.
import { Button, EmptyState } from "@umriss-ui/core";
export default function NothingYet() {
return (
<EmptyState
title="No reports yet"
description="Reports you save from the budget overview appear here."
action={
<Button variant="primary" size="sm">
Open the budget overview
</Button>
}
/>
);
}
When filters empty a list, name them in the description and offer to clear them – the data is there, the view hides it.
import { useState } from "react";
import { Button, EmptyState, Stack, Tag, TagGroup, Text } from "@umriss-ui/core";
/** Today's shipments from East Gate depot. */
const SHIPMENTS = [
{ id: "SH-1042", customer: "Harlow Bakery", status: "delivered" },
{ id: "SH-1043", customer: "Pine & Oak Florist", status: "out for delivery" },
{ id: "SH-1044", customer: "Moreau Optics", status: "delivered" },
];
export default function AFilterFoundNothing() {
const [filters, setFilters] = useState(["Failed attempt", "East Gate depot"]);
const shown = filters.includes("Failed attempt") ? [] : SHIPMENTS;
return (
<Stack gap={3}>
<TagGroup aria-label="Active filters">
{filters.map((filter) => (
<Tag key={filter} tone="accent" onRemove={() => setFilters((all) => all.filter((f) => f !== filter))}>
{filter}
</Tag>
))}
</TagGroup>
{shown.length === 0 ? (
<EmptyState
title="No shipments match these filters"
description={`Nothing today matches ${filters.map((f) => `“${f}”`).join(" and ")}.`}
action={
<Button size="sm" onClick={() => setFilters([])}>
Clear the filters
</Button>
}
/>
) : (
shown.map((shipment) => (
<Text key={shipment.id} size="sm">
{shipment.id} · {shipment.customer} · {shipment.status}
</Text>
))
)}
</Stack>
);
}
An empty panel can be the good case; an icon and a plain title say so, and no action is needed.
import { Card, CardBody, CardHeader, EmptyState } from "@umriss-ui/core";
function Check() {
return (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<circle cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="1.5" />
<path d="M7.5 12.5l3 3 6-6.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
</svg>
);
}
export default function InAPanel() {
return (
<Card style={{ maxWidth: 420 }}>
<CardHeader eyebrow="Identity" title="Open incidents" />
<CardBody>
<EmptyState
icon={<Check />}
title="No open incidents"
description="The last one, INC-1045, was resolved yesterday at 15:05."
/>
</CardBody>
</Card>
);
}
The keys of Button and Tag apply here.
EmptyStateProps| Name | Type | Default | Description |
|---|---|---|---|
titlerequired | ReactNode | — | What is missing here - as a statement, not as an apology. Shown in: Nothing yet, Say why a filter found nothing, Mark good news in a panel and 3 more |
description | ReactNode | — | One sentence on why nothing is here and what would put something here. Shown in: Nothing yet, Say why a filter found nothing, Mark good news in a panel and 3 more |
action | ReactNode | — | The way into the next action, e.g. a button. Shown in: Nothing yet, Say why a filter found nothing, Cards on a dashboard (Card) and 1 more |
icon | ReactNode | — | Optional symbol above the title. Shown in: Mark good news in a panel |
ref | Ref<HTMLDivElement> | — | Receives the component's root element. from RefPropShown in: A row that holds still (Sizes), An anchored surface (Popover), Take the width of the trigger (Popover) and 2 more |
Also takes every attribute of <div> – without title.