Feedback

Empty state

Empty pages, empty lists, zero results: a serif title with one italic word, one clear next step, and a scene per intent that the host gives.

Live example

Import

Each family is its own entry point, so a page loads only what it uses.

tsx
import { Button } from "@nibapp/ui/components/button";import { EmptyState, EmptyStateScenesProvider } from "@nibapp/ui/components/empty-state";

Props

Each component's own props and variants, read from its source. What it also takes from an element or a Base UI part is named below its table.

Button

PropTypeDefaultDescription
variant"primary" | "secondary" | "ghost" | "quiet" | "danger" | "danger-ghost" | "link""secondary"
primary
Neutral ink: the main call to action. Actions are ink, never the accent.
secondary
Quiet surface with a hairline — the default for most actions.
ghost
No chrome until hovered — toolbars, inline actions.
quiet
Words that are also an action, in the text's own weight and laid out from the start, so they line up with the text around them: `xs` in a line (a header's crumbs, a title that renames), `sm` a toolbar's picker, `md` a row in a list or a popover ("Open settings", a sidebar's link).
danger
Destructive confirmation.
danger-ghost
Destructive but low emphasis.
link
Inline text action.
size"xs" | "sm" | "md" | "lg""md"
blockboolean—
truncateboolean—

The button may shrink below its label's width; the label then truncates with an ellipsis.

wrapboolean—

The label wraps onto more lines and the button grows, its `leading` icon on the first line: for words that are an action and may run long in another language (a tip). One line keeps the size.

loadingbooleanfalse

Shows a spinner, keeps the button's width, and blocks interaction.

leadingReactNode—

Icon rendered before the label.

trailingReactNode—

Icon or hint (e.g. <Kbd>) rendered after the label.

disabledReasonstring | undefined—

Disables the button and says why: the reason is its tooltip and its accessible description, and the button stays focusable (`aria-disabled`) so a keyboard reaches it.

Also takes .

EmptyState

Calm placeholder for empty lists, blank sessions and zero-result searches.

PropTypeDefaultDescription
size"compact" | "spacious""spacious"
iconReactNode—

Small glyph shown in a raised tile.

illustrationReactNode—

Larger artwork (e.g. the mascot); replaces the icon tile.

intentEmptyStateIntent"empty"

What this place is about (default `empty`): with neither `illustration` nor `icon`, it shows the scene `EmptyStateScenesProvider` gives for it.

title (required)ReactNode—

Set in the serif. Put one word in `<em>` for its italic accent; a translated string marks it with `richText` and an `em` element, so each language picks its own word.

descriptionReactNode—
actionsReactNode—

Buttons — usually one primary and one secondary at most.

level1 | 2 | 33

The title's heading level: 3 inside a page or panel that has its own heading, 1 when the empty state is the whole page (a not-found or crash screen).

animatedbooleantrue

Play the staggered entrance. Disable for states that flicker in and out.

Also takes the props of a <div> element, except title.

EmptyStateScenesProvider

Gives every `EmptyState` below a default scene per intent: the art it shows when it's given neither an `illustration` nor an `icon`. The kit has no art of its own, so without a provider those show none.

PropTypeDefaultDescription
scenes (required)EmptyStateScenes—
children (required)ReactNode—