# Empty Inbox Illustration — React Empty State

> An inbox-zero state with an animated SVG tray: a paper plane loops overhead on a dashed trail while the tray bobs and sparkles blink.

- Category: [Empty States](https://pixelpapa.com/components/empty-states.md)
- Tags: empty-state, inbox, illustration, svg, loop
- Dependencies: motion (plus React and Tailwind CSS v4)
- Last updated: 2026-11-13
- Live preview: https://pixelpapa.com/components/empty-states/empty-inbox-illustration

## Install

```bash
npx shadcn@latest add "https://pixelpapa.com/r/empty-inbox-illustration.json"
```

The file is written to `components/pixelpapa/empty-inbox-illustration.tsx`. To install manually, run `npm install motion` and copy the source below into your project. It imports `cn` from `@/lib/utils`, which every shadcn project has.

## Source

```tsx
"use client";

import { motion, useReducedMotion } from "motion/react";

export function InboxIllustration({ className }: { className?: string }) {
  const reduce = useReducedMotion();
  return (
    <svg viewBox="0 0 220 150" className={className} aria-hidden>
      <path d="M30 62C60 10 150 4 186 44" fill="none" className="stroke-muted-foreground/40" strokeWidth="1.5" strokeDasharray="3 6" strokeLinecap="round" />
      <motion.g
        animate={reduce ? undefined : { x: [0, 78, 156], y: [0, -38, -18], rotate: [-28, 4, 30], opacity: [0, 1, 0] }}
        transition={{ duration: 3.4, repeat: Infinity, ease: "easeInOut", repeatDelay: 0.5 }}
        initial={{ x: 78, y: -38, rotate: 4 }}
      >
        <path d="M22 60 50 52 34 72l-2-9Z" className="fill-primary" />
        <path d="M32 63 50 52 34 72Z" className="fill-primary/60" />
      </motion.g>
      <motion.g animate={reduce ? undefined : { y: [0, -4, 0] }} transition={{ duration: 3.4, repeat: Infinity, ease: "easeInOut" }}>
        <ellipse cx="110" cy="138" rx="62" ry="6" className="fill-foreground/[0.07]" />
        <path d="M62 74h96l18 34v18a8 8 0 0 1-8 8H52a8 8 0 0 1-8-8v-18Z" className="fill-card stroke-border" strokeWidth="2" strokeLinejoin="round" />
        <path d="M44 108h40a6 6 0 0 1 6 6 6 6 0 0 0 6 6h28a6 6 0 0 0 6-6 6 6 0 0 1 6-6h40" fill="none" className="stroke-border" strokeWidth="2" />
        <path d="M70 84h80M74 94h72" className="stroke-muted-foreground/25" strokeWidth="3" strokeLinecap="round" />
        <circle cx="110" cy="126" r="0" className="fill-primary" />
      </motion.g>
      {[
        { x: 40, y: 40, d: 0 },
        { x: 182, y: 78, d: 0.9 },
        { x: 150, y: 22, d: 1.7 },
      ].map((s) => (
        <motion.path
          key={s.x}
          d={`M${s.x} ${s.y - 7}q1 6 7 7-6 1-7 7-1-6-7-7 6-1 7-7Z`}
          className="fill-chart-4"
          style={{ transformOrigin: `${s.x}px ${s.y}px` }}
          animate={reduce ? undefined : { scale: [0.3, 1, 0.3], opacity: [0.3, 1, 0.3] }}
          transition={{ duration: 2.4, repeat: Infinity, delay: s.d }}
        />
      ))}
    </svg>
  );
}

export default function EmptyInboxIllustration() {
  return (
    <div className="w-full max-w-md rounded-3xl border border-border bg-card px-8 py-10 text-center">
      <InboxIllustration className="mx-auto w-56" />
      <h3 className="mt-4 text-xl font-semibold tracking-tight text-card-foreground">Inbox zero. Enjoy it.</h3>
      <p className="mx-auto mt-2 max-w-xs text-sm text-muted-foreground">
        You answered 23 conversations today. New messages from customers will land here.
      </p>
      <div className="mt-6 flex justify-center gap-2">
        <button type="button" className="h-10 rounded-full bg-primary px-5 text-sm font-medium text-primary-foreground shadow-lg shadow-primary/25 transition-transform hover:-translate-y-0.5">
          Compose message
        </button>
        <button type="button" className="h-10 rounded-full border border-border px-5 text-sm font-medium text-foreground hover:bg-muted">
          View archived
        </button>
      </div>
    </div>
  );
}
```

## AI prompt

```text
Add the "Empty Inbox Illustration" component from PixelPapa UI to this project.

What it is: An inbox-zero state with an animated SVG tray: a paper plane loops overhead on a dashed trail while the tray bobs and sparkles blink.
Category: Empty States. Depends on: motion.

1. Install it with the shadcn CLI:
   npx shadcn@latest add "https://pixelpapa.com/r/empty-inbox-illustration.json"
   (If the CLI is unavailable, fetch that URL, write files[0].content to components/pixelpapa/empty-inbox-illustration.tsx and install the listed dependencies.)
2. Import it from "@/components/pixelpapa/empty-inbox-illustration" and place it where I describe below.
3. Keep its animation timings and accessibility attributes. Replace the demo copy and data with content that fits my product, and use my existing theme tokens (bg-background, text-foreground, bg-primary, border-border) rather than hard-coded colours.

Where to use it: <describe the page and position here>
```

## More empty states

- [Empty Error Retry](https://pixelpapa.com/components/empty-states/empty-error-retry.md) (Pro): A failed-to-load state with a flickering unplugged-cable drawing and a retry button that spins, fails once with a shake, then reconnects with a spark.
- [Empty First Project](https://pixelpapa.com/components/empty-states/empty-first-project.md): A first-run dropzone whose dashed border marches, tightens and tints while a file is dragged over it, with a primary action and starter templates.
- [Empty Search No Results](https://pixelpapa.com/components/empty-states/empty-search-no-results.md): A no-results state with a scanning magnifier, a working search field and suggestion chips that stagger in and fill the query when clicked.
