import { Meta, Canvas, Controls } from '@storybook/addon-docs/blocks'
import * as EmptyStateStories from './EmptyState.stories'

<Meta of={EmptyStateStories} />

# EmptyState

The place where content will be once there is some, in two manners: a
16px icon over a centred line when the whole page is empty, the line
alone and left-aligned when one section of a page is.

<Canvas of={EmptyStateStories.Page} />

## When

- **`page`** — the whole page is empty: no items yet, a link that leads to
  nothing. The icon over a centred line; `icon` swaps the default speech
  bubble for one that matches the subject.
- **`section`** — one section of a page is empty and the page has other
  things on it: no replies under an item, a search with no results. The
  line alone, left-aligned, no icon, in the quiet look — 12px caption in
  the muted colour, like a Field's helper line. A section's emptiness is
  one line among the page's content, not a stage of its own.

<Canvas of={EmptyStateStories.Section} />

The page decides, not the size of the box: a whole page with one short
message is still a `page`; a tall section with nothing in it is still a
`section`. The message says **what would fill it** — "No comments yet.
Start the thread." — not just that it is empty.

A `page` sits in the middle of its box both ways. Inside a flex column
— the frame's `main` is one — it takes the room left (`flex-1`) and
centres in it, with nothing to add; only outside a flex column does it
need a height from the caller (`className="h-full"`).

## When not

- Data is still on its way → **Skeleton**: **SkeletonList**, or a shape of
  your own from **SkeletonBar**; empty and loading are different truths.
  When the shape of what arrives is unknown, an EmptyState that says so —
  "Opening…" — is fine.
- Something went wrong → say what failed, in words. An EmptyState can carry
  it, in its usual look — never red. An empty state that hides a failure
  misleads.

## How

```tsx
import { EmptyState } from '@estiva-app/ui'

// the whole page, in the frame: it fills and centres on its own
<EmptyState message="No documents yet. Create the first one." />

// one section of a page
<EmptyState scope="section" message="No comments yet." />
```

**When there is one thing to do about it, give it as `action`.** It is drawn
16px under the line as the package's Button, outlined — the same look wherever
it appears. Never put a Button beside an EmptyState in a
box of your own: the box places it, and no two boxes place it alike. A `page`
only; a section's line takes no action.

<Canvas of={EmptyStateStories.WithAction} />

```tsx
<EmptyState icon={<IconMessagePlus size={16} stroke={1.5} />} message="Nothing here yet." action={{ label: 'Create', onClick: create }} />
```

**Put a section's empty state inside the box its rows live in, and give it no
padding.** Write the box once; inside it goes either the rows or the empty
state. The box's padding then places both, and the line starts where the first
row would. An empty state drawn *instead of* the box has to copy the box's
padding by hand, and is left behind the day the box changes.

<Canvas of={EmptyStateStories.InsideTheRowsBox} />

```tsx
<div className="flex flex-col gap-2 p-4">
  {items.length ? items.map((item) => <Row key={item.id} {...item} />) : <EmptyState scope="section" message="No items yet." />}
</div>
```

The message is the caller's — a shared component has no words of its own
for what is missing. A hand-written "Nothing here" paragraph or span in a
section is the `section` manner, and becomes it. The lint refuses one
(`estiva/no-handmade-empty-state`): a line of words that shows in place of an
empty list, whatever it says.

## What it owns

It does these by itself. Write none of them around it.

| It does | So you never write | Refused when written by hand |
|---|---|---|
| As a `page`, fills the room it is given and centres itself in it | centring, or padding around it | a box of its own that centres or pads a `page`, and a `page` inside a `ScrollArea`, where it cannot centre (`estiva/no-handmade-empty-state`) |
| Says a list is empty, in place of its rows | a paragraph or span of your own saying so | `estiva/no-handmade-empty-state` |
| Draws its one action, an outlined Button, under the line when you pass `action` | a button of your own under the line |  |

## Props

<Controls of={EmptyStateStories.Page} />
