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

<Meta of={ScrollAreaStories} />

# ScrollArea

A region that scrolls without taking width for its scrollbar. The bar is
drawn over the content and shows whenever there is more to scroll to, so a
long list says so before anyone hovers it; nothing moves when it appears.

<Canvas of={ScrollAreaStories.Default} />

## When

- Any box that can hold more than fits — **a list that grows with its data
  counts, even when today's data fits**: a menu or a dropdown list, a panel, a
  sidebar, the page's content column. Not a rail: a rail does not scroll, on
  purpose.
- `orientation="horizontal"` for a row wider than its box — a table, a
  board; `"both"` when a thing can run over either way.

<Canvas of={ScrollAreaStories.Horizontal} />

## When not

- A box that never overflows. A ScrollArea around it changes nothing, and
  is one more element.
- The page itself. The browser owns that bar.
- A whole list column → **ListColumn**, which scrolls its rows itself.

No alternative for the first two: a box that never overflows needs nothing
around it, and the page's bar is the browser's.

## How

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

<ScrollArea className="h-[240px]" contentClassName="flex flex-col p-2">
  {rows}
</ScrollArea>
```

- Three boxes, and each class prop lands on one. `className` is the
  region: its size and placement. `viewportClassName` is the box that
  scrolls: a `max-h-*` cap goes there and nowhere else. `contentClassName`
  is the box the children sit in: the padding, the gap, `flex flex-col`.
- The region needs a height to have anything to scroll. A cap on the region
  lets the viewport grow to its content and nothing scrolls; cap the
  viewport instead: `viewportClassName="max-h-[240px]"`.
- **`viewportRef` and `onScroll` hand back the box that scrolls**, for a
  region that reads or drives its own scrolling: a conversation that arrives
  at its newest message, keeps its place when older ones load above it, and
  jumps to the bottom when a reply is sent. Nothing else here can do that for
  the caller, and the caller cannot do it without the box.
- The native scrollbar is hidden by Base UI; a native `overflow-y-auto` on
  the same element would draw a second one.
- A region keeps the wheel only in an axis it can actually scroll: a list
  that reaches its end does not hand the wheel to the page behind it, but a
  sideways table inside a scrolling page passes a wheel *down* through to
  the page, and a region whose content fits passes everything. Measured in
  Chrome: wheel down over a sideways region inside a page, the page moves
  and the region does not; a sideways swipe, the other way round.

- Text inside can look a touch lighter than outside: that is Chrome drawing a
  scrolling layer, not a colour. Nothing to fix.

## 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 |
|---|---|---|
| Scrolls with our scrollbar | `overflow-auto` or `overflow-scroll` | ✓ |
| Scrolls with the keyboard when it has focus, like any scrolling box | key handlers |  |

## Keys

| Key | Does |
|---|---|
| ↑ ↓ | scroll the viewport when it has focus, as any scrolling box |
| Page Up / Down, Home, End | as any scrolling box |

## Gaps, stated

- The bar has no arrows and no click-on-track paging; the wheel, the keys
  and dragging the thumb are the ways to move.

## Props

<Controls of={ScrollAreaStories.Default} />
