Panes
Divides a box into regions with a draggable bar between each pair. Use it for an editor beside a file list, a preview beside a form, or any split whose proportions the reader decides.
import { Pane, Panes } from 'neba';
<Panes>
<Pane defaultSize="240px" minSize="160px">
Files
</Pane>
<Pane>Editor</Pane>
</Panes>;Panes fills the box it is in, so give that box a height.
Props
Panes
| Prop | Type | Default | Description |
|---|---|---|---|
| orientationshared | 'horizontal' | 'vertical' | 'horizontal' | Which way the panes run. horizontal puts them side by side with upright handles between them; vertical stacks them |
| resizable | boolean | true | Whether the handles can be dragged. Turn it off for a split that is a layout rather than a control |
| sizeshared | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' | A handle's thickness, which is the width of the target the pointer has to hit. What is drawn is a hairline; what can be grabbed is wider |
| colorshared | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'primary' | The family the handles light up in. A Panes draws no sheet, so the colour only shows in the hairline and the focus ring |
| onResize | (sizes: number[]) => void | — | Fires with every pane's share, in percent, while a handle is dragged |
| onResizeEnd | (sizes: number[]) => void | — | Fires once, with the same shape, when the handle is let go |
| children | ReactNode | — | The Panes. The constraints are read off the children’s props, so the direct children have to be Panes: a Pane wrapped in something else is a pane with no minimum |
Every other <div> attribute passes through. The direct children have to be Panes: the constraints are read off their props. The shared axes are in prop conventions.
Pane
| Prop | Type | Default | Description |
|---|---|---|---|
| defaultSize | number | string | — | The share this pane starts with. A number is a percentage; a string is a length (240px, 15rem, 20%). Panes with no defaultSize split what is left equally |
| minSize | number | string | 0 | How small it may be dragged, which is also its neighbour's ceiling |
| maxSize | number | string | — | How large it may be dragged. Unbounded when left out |
| children | ReactNode | — | What is inside the pane. A Pane carries no surface of its own, so put a Box or a Card in it when one is wanted |
Every other <div> attribute passes through.
Examples
orientation
horizontal lays the panes out side by side with upright bars between them; vertical stacks them with bars across. A bar always runs across the axis the panes run along.
defaultSize, minSize and maxSize
All three take a number, read as a percentage, or a CSS length: '240px', '15rem', '20%'. Panes with no defaultSize split whatever is left over equally. A pane's minSize is also its neighbour's ceiling, so a drag stops at whichever bound it reaches first.
onResize reports every pane's share in percent while the bar moves; onResizeEnd fires once when it is let go.
Nesting
A Panes inside a Pane is a split inside a split, which is how a three-region layout is built. Give the inner one the other orientation.
<Panes>
<Pane defaultSize="240px">Files</Pane>
<Pane>
<Panes orientation="vertical">
<Pane defaultSize={70}>Editor</Pane>
<Pane>Terminal</Pane>
</Panes>
</Pane>
</Panes>resizable
resizable={false} leaves the bar as a rule between the panes: it is still drawn, but it cannot be dragged and it is out of the tab order.
Accessibility
- Each bar is a
separatorwitharia-valuenowcarrying the share, in percent, of the pane in front of it. - A bar takes focus. ArrowLeft and ArrowRight move a upright bar; ArrowUp and ArrowDown move one that lies across.
aria-orientationdescribes the bar, not the panes: an upright bar between panes that run across isvertical.- A drag under RTL moves the boundary the way the pointer went.