Empty

A centered placeholder for a region that has nothing to show — a list with no rows, a search with no results, a page awaiting its first resource.

Empty fills a container that would otherwise be blank: a framed icon, a short headline, a line of supporting copy, and room for one or two actions that lead the user out of the empty state. It’s the component you reach for when the zero case is a normal, expected outcome rather than an error.

Don’t use Empty for failures or missing permissions — those want an <Alert> with recovery context. Use Empty when the region simply has no data yet and the user can do something about it: create the first resource, adjust a filter, connect an integration.

Import

import { Empty } from "@unkey/ui";

The component is a compound: Empty is the wrapper, and Empty.Icon, Empty.Title, Empty.Description, and Empty.Actions are the slots.

Default

With no icon child, Empty.Icon renders the Ufo glyph from @unkey/icons inside a framed tile with crosshair dividers. Use the default when the region is empty in a generic, friendly way and no specific icon adds meaning.

Nothing here yet

When you create your first resource, it will show up here.

Custom icon

Pass any icon from @unkey/icons as the child of Empty.Icon to replace the default. The framed tile, the crosshair dividers, and the 28px sizing are preserved — only the glyph changes.

No matches

We couldn’t find anything for that query. Try a shorter search term or clear your filters.

With actions

Empty.Actions is a centered flex row with a small top margin and a gap between children. Put one primary action and, optionally, a secondary outline or ghost button beside it. Two actions is the ceiling — more than that turns the empty state into a menu.

No keys yet

Create your first API key to start authenticating requests against this workspace.

Headline only

Every slot is optional. For dense layouts (a small table cell, a sidebar panel) you can drop the description and keep just the icon and title.

No activity in the last 24 hours

Accessibility

Empty is a plain <div> with no implicit role. It’s a visual affordance, not a live region — screen readers read it as the heading and paragraph inside.

Empty.Title renders as <h2>. If the empty state is nested below an existing <h2> on the page, the heading hierarchy will skip. In that case, override with a wrapping <h3> at the call site and pass plain text into Empty.Title’s children, or restyle via className.

Any button placed inside Empty.Actions keeps its native semantics; follow the usual <Button> accessibility rules (accessible name, sensible aria-label for icon-only buttons).

Props

Empty

The outer wrapper. A flex column that fills its parent (h-full w-full) and centers its children vertically and horizontally with 2rem of padding.

className string Optional

Additional Tailwind classes. Override h-full when the empty state should size to its content (h-auto), or tighten padding (p-4) in compact layouts.

children ReactNode Optional

Typically <Empty.Icon>, <Empty.Title>, <Empty.Description>, and <Empty.Actions>, in that order. All are optional.

...rest HTMLAttributes<HTMLDivElement> Optional

Standard div attributes pass through — useful for role="status" when you want assistive tech to announce the empty state as it appears.

Empty.Icon

A 7rem square tile containing a 4rem framed glyph, flanked by thin crosshair dividers. If no child is provided, renders the Ufo icon from @unkey/icons at iconSize="2xl-regular".

className string Optional

Additional Tailwind classes applied to the outer 7rem container. The inner framed tile’s size and border are not exposed — restyle with a wrapping element if you need a different frame.

children ReactNode Optional

The glyph to render inside the framed tile. Any icon from @unkey/icons works; the tile constrains SVGs to 1.75rem ([&_svg]:size-7). When omitted, defaults to <Ufo iconSize="2xl-regular" />.

Empty.Title

Renders as <h2> with semi-bold weight, 15px size, and 1.5rem leading. The headline sits 0.75rem below the icon.

className string Optional

Additional Tailwind classes. Override text-accent-12 when the empty state is placed on a colored surface, or tighten mt-3 when combined with a larger icon.

children ReactNode Optional

The headline text. Keep it to a short phrase — “No keys yet”, “Nothing to show”. Long sentences belong in <Empty.Description>.

...rest HTMLAttributes<HTMLHeadingElement> Optional

Standard heading attributes pass through (id for aria-labelledby, etc.).

Empty.Description

Renders as <p> in the muted text-accent-11 color at 12px size with 1.5rem leading and a 0.25rem top margin.

className string Optional

Additional Tailwind classes. Widen with max-w-sm mx-auto when the copy wraps awkwardly in a wide container.

children ReactNode Optional

Supporting copy — one or two sentences that explain the empty state and hint at the next step.

...rest HTMLAttributes<HTMLParagraphElement> Optional

Standard paragraph attributes pass through.

Empty.Actions

Horizontal flex row, centered, with a 1rem gap between children and a 0.5rem top margin. Intended for one or two <Button>s.

className string Optional

Additional Tailwind classes. Switch to flex-col gap-2 for stacked actions in narrow containers.

children ReactNode Optional

Usually one primary <Button> and, optionally, a secondary outline or ghost button beside it.

...rest HTMLAttributes<HTMLDivElement> Optional

Standard div attributes pass through.

  • Alert — for failure or permission states that need to announce themselves.
  • Card — when the empty region is a panel that should carry its own border.
  • Button — for the action(s) inside <Empty.Actions>.