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

<Meta of={TopBarStories} />

# TopBar

The 52px top bar: `menu` and `logo` on the left, the search field in the
centre, the identity cluster on the right. Three manners — **`solid`**,
in flow with a hairline and a surface; **`inset`**, in flow with neither,
standing on the ground; and **`floating`**, an overlay with neither, whose
bar ignores the pointer so the content underneath stays reachable.

<Canvas of={TopBarStories.Solid} />

<Canvas of={TopBarStories.Floating} />

## When

- **`solid`** — the structured frame's first row, above the sidebar
  (AppShell's `solid` variant wires exactly this).
- **`inset`** — the first row of AppShell's `inset` frame, on the ground
  above a sidebar that is on the ground too.
- **`floating`** — an app whose content runs to the top edge; the bar
  floats over it and only its clusters catch clicks (AppShell's
  `floating` variant).
- `menu` is the menu button, in an app whose navigation collapses — the
  collapsing itself stays the caller's. `logo` sits beside it: the app's
  name as text, or a mark.
- `onSearch` is what searching opens — your command launcher. With it the
  bar draws the search field itself: **SearchInput**'s look, 290px, as a
  button showing `searchPlaceholder` ("Search…") and the shortcut. A click on
  it, and Ctrl+K (Cmd+K on a Mac) anywhere on the page, call `onSearch`.
- The centre holds its place even while empty, so search drops in later
  without moving anything.

<Canvas of={TopBarStories.FloatingNoSearch} />

## When not

- Page-level headers inside the content → not this; this is the frame's
  bar, once per app. The top of a column is **ContainerHeader**.
- Anything the bar would need to know — who you are, what is searched —
  stays outside: pass composed slots, and what searching opens as `onSearch`.
- A search field of your own in the centre → only for something the bar's
  does not do; pass it as `search`, which takes the centre (`onSearch` still
  answers Ctrl+K). A field that filters a list sits above that list:
  **SearchInput**.

## How

```tsx
import { TopBar, IdentityMenu } from '@estiva-app/ui'

<TopBar
  logo="Estiva"
  onSearch={openLauncher}
  searchPlaceholder="Search Estiva…"
  right={<IdentityMenu me={me} signedIn={signedIn} />}
/>
```

- Geometry is fixed: 52px, `pl-5 pr-[26px]`, right cluster `gap-[6px]` —
  don't restyle it per app.
- `onSearch` is called on every Ctrl+K, open or not: to close the launcher
  on a second Ctrl+K, toggle in your handler.
- A click on the field leaves focus where it was, so a launcher can act on the
  text box and the selection you were in. Tab still reaches the field.
- The frame is desktop-only for now — there is no narrow-screen
  behaviour; the menu button collapses panels, it does not open a drawer.

- The bar is 52px tall, 20px in on the left and 26px on the right, 16px between
  its slots.

## 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 |
|---|---|---|
| Keeps its 52px in a scrolling column | `shrink-0` |  |
| Answers Ctrl+K (Cmd+K) anywhere on the page, given `onSearch` | a `keydown` listener on the window |  |

## Props

<Controls of={TopBarStories.Solid} />
