Resizable

Panes with a draggable, keyboard-operable divider.

Usage

Handle index is the pane on its leading side — the one whose share it reports as aria-valuenow and points aria-controls at.

label is required. A separator with a tab stop is a control, and one that announces only "splitter, 40" gives a keyboard user a number without saying what it sizes.

Sidebar

Content

The keyboard contract

This is the half every hand-rolled divider skips, and it is the difference between a splitter and a decoration. Tab to the handle above and try it.

  • Arrow keys — move the boundary by step (5% by default). Left/Right in a horizontal group, Up/Down in a vertical one.
  • Home / End — collapse and expand, as far as the panes' own limits allow.
  • Focus ring — the handle is a real tab stop with role="separator", aria-orientation and live aria-valuenow.

Two implementation details that only show up in use: the drag uses setPointerCapture, so it survives the pointer leaving a hairline target — which it does immediately — and the grabbable area is grown to 12px by a pseudo-element, so the divider can stay 1px wide without being unreasonable to hit.

Vertical

Note that aria-orientation on the handle is the opposite of the group's direction: it describes the separator's own line, not the direction of travel.

Editor

Console

Limits and clamping

A drag moves one boundary and touches exactly two panes, clamped against both of their limits before anything is applied. Distributing a drag across the whole group is what produces the familiar bug where dragging one divider quietly reflows the far side of the layout.

Clamping only the pane being grown is the other half of that bug: it lets the neighbour shrink past its own minimum. min defaults to 10 — pass min=0 if a pane should be able to disappear entirely.

Sizes are not persisted. Where that belongs — a cookie, a user profile, localStorage — is an application decision, and guessing it wrong is worse than not guessing.

Files

Editor

Inspector

Props

Each part also takes its native element's attributes via prop spreading.

PropTypeDefault
direction Direction'horizontal'
class Extra classes merged onto the group.string
children required Snippet
PropTypeDefault
min Smallest share of the group this pane accepts, in percent.number10
max Largest share, in percent.number90
class Extra classes merged onto the pane.string
children required Snippet
PropTypeDefault
index required Index of the pane on the leading side of this handle — the one whose size `aria-valuenow` reports.number
label The handle's accessible name, e.g. "Resize sidebar". Required. A `separator` with a tabindex is a control, and a control that announces only "splitter, 40" tells a keyboard user a number without saying what it sizes.string
step Percent moved per arrow-key press.number5
class Extra classes merged onto the handle.string