Ansora empty state
What a region shows when it is empty, when its fetch failed, or when the emptiness is good news. Both strings are required props — a built-in default would ship the same Czech sentence into five products.
primitive
Install
pnpm dlx shadcn@4.23.0 add @ansora/empty-stateExamples
Usage
Both visible strings are required props with no default: title and description. That is the whole point of the component — a built-in "Žádná data." would ship the exact copy web-ui-conventions forbids into five products at once, and only the caller knows whether the emptiness is bad news ("data se nepodařilo načíst"), neutral ("v tomto filtru nikdo není") or good news ("fronta je prázdná, AI zvládá provoz"). <EmptyState title="Nic tu není" /> does not compile.
tone and icon are one decision, not two, and the type says so. The tone paints only the icon chip — the title and the description stay on the ordinary text tokens in every tone, because an empty region is not an alert banner — so a tone with nothing to paint would render pixel-for-pixel like neutral while the caller believed they had flagged a failure. <EmptyState tone="critical" title="…" description="…" /> therefore does not compile, and neither does icon={null} beside a tone (NonNullable, the same trick StatusPill uses for its label). With no tone the icon is optional and renders on the neutral chip — which is also what "the list is simply empty" means; forgetting the tone de-escalates, never escalates. The four tones are neutral | warn | critical | info; there is no green one, because green is the brand colour and never a state (§5.1).
icon is rendered aria-hidden — it repeats what the title already says. action is an optional slot that renders nothing at all when you pass nothing: a transient empty ("Spojení ztraceno, obnovujeme") must not offer a manual retry beside an automatic retry loop, and a happy-path empty has nothing to do. Pass a Button, or a pair of them, when there genuinely is a next step.
This composes upstream @shadcn/empty for the layout, so shadcn add @ansora/empty-state installs components/ui/empty.tsx next to components/ui/ansora/empty-state.tsx. It is not a loading state — use upstream skeleton shaped like the content that is coming — and it is not a replacement for DataTable's emptyLabel, which is the flat one-line case inside a table body.
import { WarningIcon } from "@phosphor-icons/react/ssr"
import { EmptyState } from "@/components/ui/ansora/empty-state"
<EmptyState title="Žádní pacienti" description="V tomto filtru nikdo není." />
<EmptyState
tone="critical"
icon={<WarningIcon />}
title="Data se nepodařilo načíst"
description="Zkuste to prosím znovu za chvíli."
action={<Button onClick={retry}>Zkusit znovu</Button>}
/>
Files
registry/ansora/ui/empty-state.tsx→@ui/ansora/empty-state.tsx
Dependencies
@ansora/basehttps://ui.shadcn.com/r/styles/base-nova/empty.json