Add this component

npx zentauri-ui add empty-state

Accessibility notes

Keyboard accessible by default with semantic markup, visible focus treatment, and tokenized states. Add descriptive labels for icon-only or decorative usage.

Dependency notes

Static imports do not pull framer-motion. Use the animated entry only when you want motion and have framer-motion installed.

Layout

Empty states for zero-data views

Empty states explain why a list is blank and what to do next—search again, reset filters, or create a record. Drop them into React tables and Next.js dashboards to avoid dead-end screens.

No messages yet

When conversations arrive, they will show up here.

Examples

Ghost appearance for inline panels.


No uploads

Drag files here to add them.

Empty State variants playground

Pick an appearance, size, and alignment to preview the empty state live. Toggle Show output / Show code and the snippet updates to match the selected variant.


Appearance: DEFAULT, Size: MD, Align: CENTER

No uploads

Drag files here to add them.

All appearances

Every shipped appearance token at a glance. Click any swatch to load it into the playground above.

Empty State API

Generated from the package prop types and variant definitions.

EmptyState

EmptyStateProps

Variants

PropTypeDefault
align
centerendstart
center
appearance
aquabluecardcrimsoncyandefaultelectricforestghostgreenlavenderlime+12
default
size
lgmdsm
md

Behavior

PropTypeDefault
asElementType | undefinednone
liveRegionboolean | 'assertive' | 'polite' | undefinednone

Content

PropTypeDefault
childrenReactNodenone
Inherited HTML props
PropTypeDefault
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLElement> | undefinednone
styleCSSProperties | undefinednone
titlestring | undefinednone

EmptyStateAnimated

EmptyStateAnimatedProps

animated

Behavior

PropTypeDefault
align'center' | 'end' | 'start' | null | undefinednone
animationEmptyStateAnimation | undefinednone
appearance'default' | 'ghost' | 'card' | 'blue' | 'cyan' | 'green' | 'lime' | 'mint' | 'ocean' | 'sapphire' | 'lavender' | 'ruby' | 'red' | 'slate' | 'zinc' | 'stone' | 'royal' | 'electric' | 'forest' | 'sunset' | 'magenta' | 'crimson' | 'aqua' | 'plum' | null | undefinednone
asElementType | undefinednone
liveRegionboolean | 'assertive' | 'polite' | undefinednone
size'md' | 'sm' | 'lg' | null | undefinednone

Content

PropTypeDefault
childrenReactNodenone
Inherited HTML props
PropTypeDefault
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLElement> | undefinednone
styleCSSProperties | undefinednone
titlestring | undefinednone

EmptyStateVariant

EmptyStateVariantProps

animated

Behavior

PropTypeDefault
align'center' | 'end' | 'start' | null | undefinednone
appearance'default' | 'ghost' | 'card' | 'blue' | 'cyan' | 'green' | 'lime' | 'mint' | 'ocean' | 'sapphire' | 'lavender' | 'ruby' | 'red' | 'slate' | 'zinc' | 'stone' | 'royal' | 'electric' | 'forest' | 'sunset' | 'magenta' | 'crimson' | 'aqua' | 'plum' | null | undefinednone
size'md' | 'sm' | 'lg' | null | undefinednone
CSS variable overrides

Empty state CSS variables

Override these empty state variables on :root, a theme selector, or a component wrapper.

140 variables

Pattern: --zui-<component>-<slot?>-<variant?>-<property>-<state?>-dark?

:root {
  --zui-empty-state-default-fg: oklch(20.8% 0.042 265.755);
  --zui-empty-state-ghost-fg: oklch(37.2% 0.044 257.287);
  --zui-empty-state-card-border: #0000001a;
  --zui-empty-state-card-bg: #ffffffe6;
  --zui-empty-state-card-fg: oklch(20.8% 0.042 265.755);
  --zui-empty-state-card-shadow: 0 8px 24px rgba(15,23,42,0.12);
  --zui-empty-state-blue-border: #2563eb;
  --zui-empty-state-blue-bg: #2563eb14;
  --zui-empty-state-blue-fg: #0f172a;
  --zui-empty-state-cyan-border: #0891b2;
  --zui-empty-state-cyan-bg: #0891b214;
  --zui-empty-state-cyan-fg: #0f172a;
  --zui-empty-state-green-border: #16a34a;
  --zui-empty-state-green-bg: #16a34a14;
  --zui-empty-state-green-fg: #0f172a;
  --zui-empty-state-lime-border: #65a30d;
  --zui-empty-state-lime-bg: #65a30d14;
  --zui-empty-state-lime-fg: #0f172a;
  --zui-empty-state-mint-border: #10b981;
  --zui-empty-state-mint-bg: #10b98114;
  --zui-empty-state-mint-fg: #0f172a;
  --zui-empty-state-ocean-border: #0284c7;
  --zui-empty-state-ocean-bg: #0284c714;
  --zui-empty-state-ocean-fg: #0f172a;
  --zui-empty-state-sapphire-border: #1d4ed8;
  --zui-empty-state-sapphire-bg: #1d4ed814;
  --zui-empty-state-sapphire-fg: #0f172a;
  --zui-empty-state-lavender-border: #8b5cf6;
  --zui-empty-state-lavender-bg: #8b5cf614;
  --zui-empty-state-lavender-fg: #0f172a;
  --zui-empty-state-ruby-border: #be123c;
  --zui-empty-state-ruby-bg: #be123c14;
  --zui-empty-state-ruby-fg: #0f172a;
  --zui-empty-state-red-border: #dc2626;
  --zui-empty-state-red-bg: #dc262614;
  --zui-empty-state-red-fg: #0f172a;
  --zui-empty-state-slate-border: #475569;
  --zui-empty-state-slate-bg: #47556914;
  --zui-empty-state-slate-fg: #0f172a;
  --zui-empty-state-zinc-border: #52525b;
  --zui-empty-state-zinc-bg: #52525b14;
  --zui-empty-state-zinc-fg: #0f172a;
  --zui-empty-state-stone-border: #57534e;
  --zui-empty-state-stone-bg: #57534e14;
  --zui-empty-state-stone-fg: #0f172a;
  --zui-empty-state-royal-border: #4338ca;
  --zui-empty-state-royal-bg: #4338ca14;
  --zui-empty-state-royal-fg: #0f172a;
  --zui-empty-state-electric-border: #0ea5e9;
  --zui-empty-state-electric-bg: #0ea5e914;
  --zui-empty-state-electric-fg: #0f172a;
  --zui-empty-state-forest-border: #166534;
  --zui-empty-state-forest-bg: #16653414;
  --zui-empty-state-forest-fg: #0f172a;
  --zui-empty-state-sunset-border: #ea580c;
  --zui-empty-state-sunset-bg: #ea580c14;
  --zui-empty-state-sunset-fg: #0f172a;
  --zui-empty-state-magenta-border: #c026d3;
  --zui-empty-state-magenta-bg: #c026d314;
  --zui-empty-state-magenta-fg: #0f172a;
  --zui-empty-state-crimson-border: #b91c1c;
  --zui-empty-state-crimson-bg: #b91c1c14;
  --zui-empty-state-crimson-fg: #0f172a;
  --zui-empty-state-aqua-border: #0f766e;
  --zui-empty-state-aqua-bg: #0f766e14;
  --zui-empty-state-aqua-fg: #0f172a;
  --zui-empty-state-plum-border: #7e22ce;
  --zui-empty-state-plum-bg: #7e22ce14;
  --zui-empty-state-plum-fg: #0f172a;
  --zui-empty-state-description-fg: oklch(55.4% 0.046 257.417);
}

/* Dark theme variables follow the same names with -dark appended. */
.dark {
  --zui-empty-state-default-fg-dark: oklch(98.4% 0.003 247.858);
  --zui-empty-state-ghost-fg-dark: oklch(92.9% 0.013 255.508);
}

What it does

Keep messaging specific: differentiate “no data yet” from “no matches.”

Offer a single primary action to reduce decision fatigue.

Composition and API

Prefer compound subcomponents instead of one oversized prop bag. Export a small, documented API for your design system.

Provide heading text that summarizes the state for screen reader users quickly.

Common use cases

  • First-run experiences before any records exist.
  • Zero-result searches with suggested next steps.
  • Permission-restricted views with upgrade CTAs.
  • Filtered tables after aggressive query narrowing.

Accessibility

Keyboard order, focus rings, and ARIA attributes should match production usage. Test with your supported browsers and assistive technologies when semantics are non-trivial.

This preview page exposes a single h1 in the hero for a clean outline.

Next.js integration notes

Colocate examples under the App Router, keep server and client boundaries explicit, and avoid pulling interactive overlays into unexpected server layouts.

Set NEXT_PUBLIC_SITE_URL so canonical and Open Graph URLs resolve on deploy.

FAQ

Does the Empty state component work with Next.js App Router?

Yes. Import it like any other React component; keep interactive subtrees in client components when you need hooks or browser APIs, and leave static structure in server components where possible.

Can I customize empty state with Tailwind CSS?

Zentauri UI exposes class-friendly variants and slots so you can extend styles with Tailwind utilities without fighting inline styles.

Is this Empty state implementation accessible by default?

Primitives follow sensible defaults, but accessibility depends on how you label controls, manage focus, and wire keyboard handlers in your app. Validate critical flows with keyboard-only use and screen readers.