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

<Meta of={NavTreeStories} />

# NavTree

A sidebar's tree from one nested list: a quiet label, groups that fold
under the standard heading with their rows lightly indented, and rows under
rows to any depth.

<Canvas of={NavTreeStories.Default} />

## When

- Places that nest, in a **Sidebar**: groups, rows in them, rows under
  those rows. Hand it the whole list; it draws every level.
- `selected` is the current row: it is `active`, and only its group starts
  open. Rows with rows under them start open.

<Canvas of={NavTreeStories.CurrentDeep} />

- A row's `hint` (a neutral **Chip**), `count` and `menu` are **NavItem**'s,
  passed through.
- `groups={null}` while the first read is on its way draws a skeleton;
  `[]` draws `emptyMessage`, level with the rows.

<Canvas of={NavTreeStories.Loading} />

- `titleActions` sit beside the label, always shown ("New"); a group's
  `actions` beside its title on hover ("Open"), its `trailing` always (an
  **UnreadDot**). A row's `unread` and `urgent` are **NavItem**'s.

<Canvas of={NavTreeStories.WithActionsAndUnread} />

- A group's `menu` is its "More options" ⋮, after its actions and its
  `trailing`: what acts on the whole group — a folder's Rename, Archive. A
  row's `menu` acts on that row.

<Canvas of={NavTreeStories.GroupMenus} />

- A group folds with a row's arrow, 16px — every folding heading does — so a
  group and the rows under it fold with the same arrow; its title starts 8px
  after it, as a row's label.
- A group's `icon` sits before its title — a folder's — and the arrow takes
  its place under the pointer, as a row's icon turns into its arrow. Its rows
  then start under the title, past the icon.

<Canvas of={NavTreeStories.GroupIcons} />

- Rows can be read as they open. A group's `nodes={null}` is a skeleton in
  its rows' place, and its `message` a line in their place ("Nothing in this
  yet."). A row with `hasChildren` and no `children` has its arrow, a
  skeleton under it once open, and `onOpenChange` says when to read them;
  `childrenMessage` is the line under it. `onIntent` on a group says the
  pointer rests on it or the keyboard reached it: read it then, so opening
  it draws rows. A `NavTreeSection` opened while its read is in flight takes
  `pending`: its arrow turns and it opens once the rows are in, in one move,
  instead of a skeleton the rows then replace; keep `loading` for a read
  that turns out slow.

<Canvas of={NavTreeStories.ReadAsItOpens} />

- An app whose groups and rows each read their own data draws the groups
  itself: leave out `groups` and pass **NavTreeSection**s as children, each
  with **NavItem** rows. A `NavTreeSection` is one group exactly as `groups`
  draws it — the heading, the light indent, `message`, `loading`, `trailing`,
  `actions`, `menu`, `icon`, `onIntent`.

<Canvas of={NavTreeStories.AppDrawnGroups} />

## When not

- A flat list of places → **NavItem** rows in the **Sidebar**.
- One group that folds, written by hand → **CollapsibleSection**.
- A list beside the thing that is open → **ListColumn**.

## How

```tsx
import { NavTree, Sidebar } from '@estiva-app/ui'

<Sidebar>
  <NavTree
    title="Groups"
    groups={groups}
    selected={currentId}
    onSelect={(node, event) => {
      event.preventDefault()
      navigate(node.href)
    }}
    emptyMessage="Nothing here yet."
    storageKey="app.sidebar.groups"
  />
</Sidebar>
```

- Each row is a **NavItem**, so a row is a link, and changes page as one
  does: through **AppProvider**'s `navigate`, or `onSelect` preventing the
  default and navigating.
- `storageKey` remembers each group open or closed in this browser, under
  the key and the group's id. The rows under a row are not remembered yet.
- The words in `emptyMessage` are the caller's.

## 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 |
|---|---|---|
| Draws every level from one list, rows under rows | a recursive render of **NavItem**s and **CollapsibleSection**s |  |
| Opens the group that holds the current row | a search through the list for the current row |  |
| Says it is loading, or empty, in the rows' place | a skeleton or an **EmptyState** placed by hand |  |
| Says when the pointer rests on a group, 150ms, and not while it sweeps past | a timer on pointer enter and leave |  |

## Keys

| Key | Does |
|---|---|
| Tab | each group's title, then its rows: each row's link, then its arrow |
| Enter, Space | on a group's title or a row's arrow: folds or unfolds |

It is not an ARIA tree yet: there are no arrow keys between rows.

## Props

<Controls of={NavTreeStories.Default} />
