A resizable screen is two panels with a handle that moves the boundary between them. The first
panel takes the size you give it, the second takes whatever is left, and the reader adjusts the
division by dragging the handle or by focusing it and pressing an arrow key. It is the layout of
an editor with a file tree, a mail client with a list beside a message, and a data tool with a
query beside its results.

It is the interactive counterpart of `Split`: a split states a ratio and keeps it, while a
resizable screen hands the ratio to the reader. The component is web-only, because a draggable
divider is a desktop idiom.

```tsx demo="layouts/resizable-screen-preview"
```

The handle is a real separator rather than a decorated border: dragging it captures the pointer,
the arrow keys move the boundary by `step`, and <kbd>Home</kbd> and <kbd>End</kbd> jump to the
clamps. `hideHandle` renders the same split without it, for the case where the division is fixed
today but the layout is not.

## Usage

```tsx
import { ResizableScreen } from "@asheeui/web";

<ResizableScreen defaultSize={35} minSize={20} maxSize={60}>
  <nav aria-label="Documents">
    <ul>
      <li>INV-1041</li>
    </ul>
  </nav>
  <article>
    <p>The invoice.</p>
  </article>
</ResizableScreen>
```

`children` is a pair of exactly two nodes, and the component reads them as a tuple: the first is
the panel the percentage applies to, the second takes the remainder, and the handle is rendered
between them. One child is a type error rather than a silent layout, because a split with one
panel has nothing to divide, that case is `Split` or a plain `Stack`.

## A size that is controlled or not

`defaultSize` seeds an uncontrolled split. The component owns the number, dragging changes it, and
`onSizeChange` is told what it became, so a page that only wants to react can listen without
taking ownership.

When `size` is given the component is controlled: it draws that percentage and reports every
request through `onSizeChange`, and the boundary only moves when the page writes the number back.
`left` is an alias for `defaultSize`, kept for callers that named the first panel's position
rather than its size.

```tsx demo="layouts/resizable-screen-controlled"
```

Sizes are percentages, so a split keeps its proportions when the window changes. A controlled
split therefore leaves the page the owner of a number it has to keep in state beside whatever else
that panel's width decides, which is the reason to control it in the first place.

## Clamps, steps and orientation

`minSize` and `maxSize` clamp the first panel as a percentage, `20` and `80` unless the instance or
`components.resizableScreen` say otherwise. Every path into the number runs through the clamp: the
drag, the arrow keys, <kbd>Home</kbd> and <kbd>End</kbd>, and the value `onSizeChange` reports.
`step` is how far one arrow press moves the boundary, `2` by default.

`orientation` states which way the split divides. `horizontal` puts the panels side by side and
resizes with <kbd>←</kbd> and <kbd>→</kbd>; `vertical` stacks them and resizes with <kbd>↑</kbd>
and <kbd>↓</kbd>.

```tsx demo="layouts/resizable-screen-vertical"
```

`minContainerWidth` and `minContainerHeight` are pixels rather than percentages, and they exist
because a split inside a parent with no definite size would otherwise collapse: the container
claims at least `200` pixels of each unless the instance or `components.resizableScreen` say
otherwise, and a definite height from the layout around it, `h-64`, a flex row, a grid row, is
what the percentage is measured against. The two are configuration as well as instance props, so a
product whose panels are never smaller than a particular size states the floor once.

## Props

```props ResizableScreen
```

`defaultSize`, `minSize`, `maxSize`, `step`, `orientation`, `minContainerWidth` and
`minContainerHeight` are registered by the component as `50`, `20`, `80`, `2`, `horizontal`, `200`
and `200`, so each resolves from the instance, then `components.resizableScreen`, then that value.
`hideHandle` is not registered: its fallback is `false`, so the handle is drawn unless the instance
or the application hides it. `left`, `size`, `onSizeChange` and `handleClassName` are statements
about one split rather than about the product, so they are instance props.

## Accessibility

- The handle is a focusable `role="separator"` with `tabindex="0"`, the pattern ARIA defines for a
  resizable split. It carries a name (`Resize panel split`), `aria-valuenow` with the first
  panel's percentage, `aria-valuemin` and `aria-valuemax` from the clamps, and `aria-orientation`
  describing the **separator's** own axis: a side-by-side split is divided by a vertical separator,
  so it reports `vertical`, and a stacked split reports `horizontal`. That is the line the
  separator draws, the opposite of the axis the panels are laid out on, and the arrows move the
  separator across it, which is why a vertical one answers to <kbd>←</kbd> and <kbd>→</kbd>.
- The keyboard contract is complete: the arrows move the boundary by `step` in the direction
  `orientation` implies, and <kbd>Home</kbd> and <kbd>End</kbd> jump to the minimum and the
  maximum. The handle can therefore be used without a pointer, which is what a resizable split
  usually fails at.
- The drag captures the pointer, so a fast drag that leaves the handle keeps resizing, and the
  handle is `touch-none`, so a scroll gesture is not stolen while the drag is in flight.
- Each panel scrolls on its own, so a long list in the first panel does not push the second out of
  view, and the panels keep the order they are written in for a reader moving through the
  document.

A resizable screen is the interactive end of the layout family; the static arrangements it sits
beside are described once in [Layout and spacing](/concepts/layout-and-spacing).

## Native

The compatibility matrix classifies this component as **web-only**, and the reason is the
interaction rather than the arrangement: a draggable divider is a desktop idiom, and a native
split view, where a platform offers one, is the platform's to draw, with its own gestures and
its own presentation. `@asheeui/native` exports nothing for it.

What to reach for on a device: `Split` for the static two-pane layout, which stacks the panes on a
narrow screen, and the platform's own split view when the user really must move the boundary. See
[React Native](/platforms/native).

## Related

```related split, grid, centered
```
