# Empty

Displays a reusable empty state with header, media, title, description, and content slots.

Use Empty for onboarding gaps, no-results screens, no-notification panels, and 404-like recovery surfaces that need a clear next action.

## Import

```ts
import {
  EmptyComponent,
  EmptyContentComponent,
  EmptyDescriptionComponent,
  EmptyHeaderComponent,
  EmptyMediaComponent,
  EmptyTitleComponent,
} from '@edsis/component/empty';
import { ButtonComponent } from '@edsis/component/button';
```

## Composition

The Angular structure follows the shadcn Empty information architecture while keeping actions on native buttons and anchors.

```text
Empty
├── EmptyHeader
│   ├── EmptyMedia
│   ├── EmptyTitle
│   └── EmptyDescription
└── EmptyContent
```

## Basic usage

```html
<Empty class="max-w-xl rounded-2xl border border-border bg-card/40">
  <EmptyHeader>
    <EmptyMedia variant="icon">
      <svg
        aria-hidden="true"
        viewBox="0 0 24 24"
        fill="none"
        stroke="currentColor"
        stroke-width="2"
      >
        <path d="M12 6v12" />
        <path d="M6 12h12" />
      </svg>
    </EmptyMedia>
    <EmptyTitle>No projects yet</EmptyTitle>
    <EmptyDescription>
      You have not created any projects yet. Start by creating a new project or importing an
      existing one.
    </EmptyDescription>
  </EmptyHeader>

  <EmptyContent class="sm:flex-row">
    <button Button type="button">Create project</button>
    <button Button type="button" variant="outline">Import project</button>
  </EmptyContent>

  <a Button href="/docs/getting-started" variant="link" class="text-muted-foreground">Learn more</a>
</Empty>
```

## Common patterns

### Outline shell

Use border utilities on the root when the empty state should read like an inset card or dashboard panel.

```html
<Empty class="rounded-2xl border border-dashed border-border">
  <EmptyHeader>
    <EmptyMedia variant="icon">...</EmptyMedia>
    <EmptyTitle>Cloud storage empty</EmptyTitle>
    <EmptyDescription>Upload files to your cloud storage to access them anywhere.</EmptyDescription>
  </EmptyHeader>
  <EmptyContent>
    <button Button type="button" variant="outline" size="sm">Upload files</button>
  </EmptyContent>
</Empty>
```

### Avatar media

Leave `EmptyMedia` on the default variant when projecting an avatar, avatar group, or any other custom artwork.

```html
<Empty>
  <EmptyHeader>
    <EmptyMedia>
      <Avatar class="size-12">
        <AvatarImage src="https://github.com/shadcn.png" alt="shadcn" />
        <AvatarFallback>CN</AvatarFallback>
      </Avatar>
    </EmptyMedia>
    <EmptyTitle>User offline</EmptyTitle>
    <EmptyDescription
      >Leave a message and they will be notified when they come back online.</EmptyDescription
    >
  </EmptyHeader>
  <EmptyContent>
    <button Button type="button" size="sm">Leave message</button>
  </EmptyContent>
</Empty>
```

### Input group recovery

Compose `EmptyContent` with the existing input-group primitives when the empty state should immediately guide recovery or search.

```html
<Empty class="max-w-xl rounded-2xl border border-border">
  <EmptyHeader>
    <EmptyTitle>404 - Not found</EmptyTitle>
    <EmptyDescription>
      The page you are looking for does not exist. Try searching for what you need below.
    </EmptyDescription>
  </EmptyHeader>
  <EmptyContent class="max-w-md">
    <InputGroup class="w-full">
      <input InputGroupInput aria-label="Search pages" placeholder="Try searching for pages..." />
      <InputGroupAddon>
        <span aria-hidden="true">⌕</span>
      </InputGroupAddon>
      <InputGroupAddon align="inline-end">
        <span
          aria-hidden="true"
          class="inline-flex h-6 items-center rounded-md border border-border bg-background px-2 font-mono text-[11px] font-medium text-foreground shadow-sm"
        >
          /
        </span>
      </InputGroupAddon>
    </InputGroup>
  </EmptyContent>
</Empty>
```

## API reference

### `EmptyComponent`

| Input   | Type     | Default |
| ------- | -------- | ------- |
| `class` | `string` | `''`    |

### `EmptyMediaComponent`

| Input     | Type                  | Default     |
| --------- | --------------------- | ----------- |
| `variant` | `'default' \| 'icon'` | `'default'` |
| `class`   | `string`              | `''`        |

### Parts

- `EmptyHeader` centers the media, title, and description stack.
- `EmptyTitle` provides the primary heading.
- `EmptyDescription` renders supporting copy with muted foreground color.
- `EmptyContent` groups actions, inputs, or recovery affordances under the header.

All Empty parts also accept a `class` input.

## Styling and theming

The primitive keeps styling neutral by default: the root controls spacing and alignment, while visual shells such as borders, gradients, and muted backgrounds are layered through `class`.

`EmptyMedia` uses `border-border` and `bg-muted/40` for the icon variant so the icon chip matches the rest of the theme without inheriting text color for borders.

Use `class` on the root or parts to add panel borders, gradient backgrounds, tighter widths, or horizontal action layouts.

## Accessibility

- Keep the title and description visible so the empty state communicates both the missing content and the next step.
- Put actions on native `<button>` or `<a Button>` hosts instead of faking interactivity with generic elements.
- Mark decorative icons inside `EmptyMedia` as `aria-hidden="true"` unless the icon itself provides unique meaning.

## Keyboard interactions

- The Empty primitives themselves are passive layout containers and do not enter the tab order.
- Projected buttons, anchors, and inputs keep their native Tab, Enter, and Space behavior.
- When `EmptyContent` contains an input group, the control remains first in the DOM so tab order stays predictable.

## Angular notes

- `Empty` is a reusable content primitive, separate from application route-shell layout concerns.
- The link action from the upstream shadcn preview maps cleanly to `<a Button variant="link">` in Angular.
- Project any custom artwork into `EmptyMedia`; only the `icon` variant applies a circular icon shell.

## Source parity

This Angular implementation follows the shadcn Empty page structure, examples, and API reference while translating React composition to Angular selectors and keeping page-shell layout concerns separate from the reusable empty-state primitive.
