# Empty

A placeholder for screens and lists with nothing to show.

Source: [empty.tsx](https://github.com/jakejarvis/jarvis-ui/blob/main/src/components/ui/empty.tsx)

```tsx
import { FolderIcon, PlusIcon } from "lucide-react";

import { Button } from "@/components/ui/button";
import {
  Empty,
  EmptyContent,
  EmptyDescription,
  EmptyHeader,
  EmptyMedia,
  EmptyTitle,
} from "@/components/ui/empty";

export default function EmptyWithActions() {
  return (
    <Empty>
      <EmptyHeader>
        <EmptyMedia variant="icon">
          <FolderIcon />
        </EmptyMedia>
        <EmptyTitle>No projects yet</EmptyTitle>
        <EmptyDescription>Create a project to start tracking tasks and files.</EmptyDescription>
      </EmptyHeader>
      <EmptyContent>
        <div className="flex gap-2">
          <Button variant="primary" size="sm">
            <PlusIcon />
            New project
          </Button>
          <Button variant="secondary" size="sm">
            Import
          </Button>
        </div>
      </EmptyContent>
    </Empty>
  );
}
```

## Installation

Add the registry, once per project:

```bash
npx shadcn@latest registry add @jarvis=https://ui.jarv.is/r/{name}.json
```

Then add the component:

```bash
npx shadcn@latest add @jarvis/empty
```

## Usage

```tsx
import { FolderIcon } from "lucide-react";

import { Button } from "@/components/ui/button";
import {
  Empty,
  EmptyContent,
  EmptyDescription,
  EmptyHeader,
  EmptyMedia,
  EmptyTitle,
} from "@/components/ui/empty";

export function NoProjects() {
  return (
    <Empty>
      <EmptyHeader>
        <EmptyMedia variant="icon">
          <FolderIcon />
        </EmptyMedia>
        <EmptyTitle>No projects yet</EmptyTitle>
        <EmptyDescription>Create a project to start tracking tasks and files.</EmptyDescription>
      </EmptyHeader>
      <EmptyContent>
        <Button variant="primary" size="sm">
          New project
        </Button>
      </EmptyContent>
    </Empty>
  );
}
```

Say why there's nothing to show and, where you can, what to do next.

`Empty` has no surface of its own: it centers its content in whatever holds it, so it can fill a page, a list or a panel. To set it apart, put it in a [Card](https://ui.jarv.is/components/card.md).

## Composition

- `Empty`
  - `EmptyHeader`
    - `EmptyMedia`
    - `EmptyTitle`
    - `EmptyDescription`
  - `EmptyContent`

## Examples

### Bare icon

Without a variant, `EmptyMedia` shows a plain icon, for lighter cases like an empty search.

```tsx
import { SearchIcon } from "lucide-react";

import {
  Empty,
  EmptyDescription,
  EmptyHeader,
  EmptyMedia,
  EmptyTitle,
} from "@/components/ui/empty";

export default function EmptyNoResults() {
  return (
    <Empty>
      <EmptyHeader>
        <EmptyMedia>
          <SearchIcon />
        </EmptyMedia>
        <EmptyTitle>No results</EmptyTitle>
        <EmptyDescription>
          Nothing matches “quarterly”. Try a different search or{" "}
          <a href="#filters">clear filters</a>.
        </EmptyDescription>
      </EmptyHeader>
    </Empty>
  );
}
```

### In a card

Put `Empty` in a card's content to show that one panel of a page has nothing in it yet.

```tsx
import { PlusIcon, ReceiptIcon } from "lucide-react";

import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import {
  Empty,
  EmptyContent,
  EmptyDescription,
  EmptyHeader,
  EmptyMedia,
  EmptyTitle,
} from "@/components/ui/empty";

export default function EmptyInCard() {
  return (
    <Card className="w-full max-w-sm">
      <CardHeader className="border-b">
        <CardTitle>Invoices</CardTitle>
        <CardDescription>Billed to Acme each month</CardDescription>
      </CardHeader>
      <CardContent>
        <Empty>
          <EmptyHeader>
            <EmptyMedia variant="icon">
              <ReceiptIcon />
            </EmptyMedia>
            <EmptyTitle>No invoices yet</EmptyTitle>
            <EmptyDescription>Your first invoice appears at the end of the month.</EmptyDescription>
          </EmptyHeader>
          <EmptyContent>
            <Button variant="secondary" size="sm">
              <PlusIcon />
              Add payment method
            </Button>
          </EmptyContent>
        </Empty>
      </CardContent>
    </Card>
  );
}
```

### Flat card

A `flat` card sets the empty state into the page with a hairline border instead of a shadow.

```tsx
import { InboxIcon } from "lucide-react";

import { Card, CardContent } from "@/components/ui/card";
import {
  Empty,
  EmptyDescription,
  EmptyHeader,
  EmptyMedia,
  EmptyTitle,
} from "@/components/ui/empty";

export default function EmptyFlatCard() {
  return (
    <Card variant="flat" className="w-full max-w-sm">
      <CardContent>
        <Empty>
          <EmptyHeader>
            <EmptyMedia variant="icon">
              <InboxIcon />
            </EmptyMedia>
            <EmptyTitle>You’re all caught up</EmptyTitle>
            <EmptyDescription>New messages from your team will show up here.</EmptyDescription>
          </EmptyHeader>
        </Empty>
      </CardContent>
    </Card>
  );
}
```

## Props

| Part | Extends |
| --- | --- |
| `Empty` | `<div>` |
| `EmptyHeader` | `<div>` |
| `EmptyMedia` | `<div>` |
| `EmptyTitle` | `<div>` |
| `EmptyDescription` | `<div>` |
| `EmptyContent` | `<div>` |

### EmptyMedia

| Prop       | Type                  | Description          |
| ---------- | --------------------- | -------------------- |
| `variant?` | `"default" \| "icon"` | Default: `"default"` |
