Empty
A placeholder for a section that currently has nothing to show.
INV-2041
Northwind Traders
$4,200.00
INV-2042
Contoso
$1,150.00
INV-2043
Fabrikam
$780.00
View code
let query = "";
let matches = INVOICES.filter((invoice) =>
`${invoice.id} ${invoice.client}`.toLowerCase().includes(query.trim().toLowerCase()),
);
<Group>
<Input
name="q"
type="search"
value={query}
placeholder="Search invoices"
aria-label="Search invoices"
mix={[
on<HTMLInputElement, "input">("input", (event) => {
query = event.currentTarget.value;
void handle.update();
}),
]}
/>
</Group>
{matches.length > 0 ? (
matches.map((invoice) => (
<Item key={invoice.id}>
<Item.Media>
<FileTextIcon aria-hidden="true" />
</Item.Media>
<Item.Content>
<Item.Title>{invoice.id}</Item.Title>
<Item.Description>{invoice.client}</Item.Description>
</Item.Content>
<Item.Actions>{invoice.amount}</Item.Actions>
</Item>
))
) : (
<Empty>
<Empty.Icon>
<SearchIcon />
</Empty.Icon>
<Empty.Title>No invoices match “{query.trim()}”</Empty.Title>
<Empty.Description>
Search runs over the invoice number and the client's name. Nothing in this workspace
matches either.
</Empty.Description>
<Empty.Action>
<Button variant="outline" color="neutral" mix={[on("click", clearQuery)]}>
Clear the search
</Button>
<Button>New invoice</Button>
</Empty.Action>
</Empty>
)}Installation
An ordinary dependency: install it, import the theme once, and import the component where it is used.
npm add @sdxc/uiimport "@sdxc/ui/theme.css";Usage
import { Empty } from "@sdxc/ui";Renders the empty-state panel: a dashed-bordered column tinted to the
color role in Empty.Props.color. Its compound parts inherit that
color through currentcolor.
Composition
The parts the component publishes, each a static property of the host.
EmptyEmpty.IconRenders Empty.IconProps.children as the icon well: a fully rounded, tinted badge framing an icon graphic hidden from assistive technology, since Empty.Title's text already names the state.Empty.TitleRenders Empty.TitleProps.children as the empty state's heading, in the native heading element matching its ambientHeadingScopedepth (or<h1>unscoped), sized as the panel's primary text regardless of level.Empty.DescriptionRenders Empty.DescriptionProps.children as the empty state's supporting copy, in a native<p>set to seventy percent of the panel's current text color so it reads as secondary to Empty.Title.Empty.ActionRenders Empty.ActionProps.children as the empty state's call-to-action slot: a centered, wrapping row spaced a touch below the text above it, so a state offering more than one action lays them out rather than running them together.
Examples
<Empty color="danger">
<Empty.Title>{t("errors.notFound.title")}</Empty.Title>
</Empty>Props
Read from the component's own types, so every prop, every default and every allowed value is listed.
| Prop | Type | Description |
|---|---|---|
color? | "brand" | "neutral" | "success" | "warning" | "danger" | Semantic tone of the panel. Default: "neutral". |
children | RemixNode | The panel's compound parts: Empty.Icon, Empty.Title, Empty.Description, Empty.Action, or any other content. |
Also accepts everything in TagProps<"div">.
Empty.Icon
| Prop | Type | Description |
|---|---|---|
children | RemixNode | Icon graphic rendered inside the icon well. |
Also accepts everything in TagProps<"div">.
Empty.Title
| Prop | Type | Description |
|---|---|---|
children | RemixNode | Heading copy for the empty state. |
Also accepts everything in TagProps<"h1">.
Empty.Description
| Prop | Type | Description |
|---|---|---|
children | RemixNode | Supporting copy elaborating on the empty state. |
Also accepts everything in TagProps<"p">.
Empty.Action
| Prop | Type | Description |
|---|---|---|
children | RemixNode | Call-to-action content, typically a button or link. |
Also accepts everything in TagProps<"div">.
Types
| Name | Values | What it decides |
|---|---|---|
Color | "brand" | "neutral" | "success" | "warning" | "danger" | Semantic tone driving the panel's border, tint, and foreground color through the --ui-* variables for that color. |