Skip to content

Empty

A centered empty-state surface — no results, first-run, or a cleared list.

Stablev0.4.2added in v0.1.0@garn/ui/empty
On this page

Default

An empty inbox with a next action.

Installation

garn is copy-in — the garn CLI writes this component's source into your project, so you own and can edit it. It resolves any base files and installs the npm dependencies below for you.

terminal
npx garn-ui add empty
First time? Set up garn in your project
Registry
empty
Deps
class-variance-authority
Registry deps
utils

Import

import { EmptyHeader, EmptyMedia, EmptyTitle, EmptyDescription, EmptyContent } from "@garn/ui/empty";

Anatomy

The parts this component is built from — compose them to assemble it.

EmptyHeaderRequired[data-slot="empty-header"]

Groups media + title + description.

EmptyMedia[data-slot="empty-media"]

Media holder. Has its own variant: icon is a tonal rounded tile for a single lucide icon; default is a bare slot for illustrations or an Avatar. (Sets data-variant.)

EmptyTitle[data-slot="empty-title"]

The headline. Identity type (fixed).

EmptyDescription[data-slot="empty-description"]

Supporting copy.

EmptyContent[data-slot="empty-content"]

Actions / secondary content below the header.

Props

The component's public props and their types.

No component-specific props — this is a thin wrapper over its native element.

Styling

Target these data-slots and states, and remap these tokens, to restyle without forking the component.

[data-slot="empty"]
PropertyTokenTier
padding--garn-pad-surfacesemantic · air
stackGap--garn-gap-stacksemantic · air
fieldGap--garn-gap-fieldsemantic · air
mediaTile--garn-mutedsemantic · identity

When to use

Communicate a blank state — no search results, nothing created yet, a cleared list.

Reach for something else when

  • For a transient loading state — use a Spinner or a Skeleton that preserves layout.

Overview

Empty communicates a blank state — no search results, nothing created yet, a cleared list — and turns a dead end into a next step. EmptyHeader groups the EmptyMedia (icon/illustration), EmptyTitle, and EmptyDescription, with EmptyContent below for an action. It's for a genuinely empty result, not a wait: use a Skeleton or Spinner while loading, and an Alert for an error.

Guidelines

Distinguish the three blanks. "Nothing yet" (onboarding), "no matches" (a filtered search), and "all done" each want different copy and actions — don't ship one generic "No data". Name which one it is and what to do about it.

Always offer a way forward. The most useful empty state includes the next action — "Create your first project", "Clear filters". For a no-results search, suggest broadening the query rather than leaving the user stuck.

Keep the tone light and the layout calm. A short title, a sentence of guidance, and one primary action; the illustration sets mood but shouldn't dominate. Don't confuse empty with error — reserve alarming language for actual failures.

Best practices

Do
  • Lead with a concise title and one clear next action in EmptyContent.
  • Use EmptyMedia variant="icon" for a single lucide icon.
Don't
  • Don't stack multiple competing actions.
  • Don't use it for errors that need an accessible alert without providing one.

Content guidelines

  • Say plainly what's missing and why, then offer one clear next step.
  • Keep the tone neutral and constructive — guidance, not an apology.

Troubleshooting

The media icon sits on a double background or wrong tile.

Cause. EmptyMedia variant="icon" already provides the tonal rounded tile.

Fix. Don't add your own background; use variant="default" for custom illustrations.

Accessibility

  • Use a real heading (or aria-labelledby pointing at EmptyTitle) where the state should be announced.
  • If it reports an error that needs attention, give the actionable message role=status or wrap it in an alert.