@lp-labs/react-split-pane
v0.1.0
Published
Accessible React split panes with pointer/keyboard resizing and layout persistence.
Readme
@lp-labs/react-split-pane
Resizable React panels with pointer/touch and keyboard controls, size constraints and optional persistence. React 18+ peer only; no runtime dependencies or CSS imports. Includes TypeScript, ESM, CommonJS and browser entries.
Installation
npm install @lp-labs/react-split-paneRequires React 18 or later in the host application. Pointer resizing requires a browser with Pointer Events. Persistence requires browser storage or a custom synchronous storage adapter. Server-side rendering is supported; Node.js consumers require Node.js 18 or later.
Quick Start
import SplitPane, { Pane } from '@lp-labs/react-split-pane';
export default function Example() {
return (
<SplitPane storageKey="editor-layout" style={{ height: 500 }}>
<Pane id="files" label="Files" defaultSize={25} minSize={15} maxSize={50}>
Files
</Pane>
<Pane id="editor" label="Editor" minSize={20}>
Editor
</Pane>
</SplitPane>
);
}Pane API
Use at least two direct Pane children; nest another SplitPane inside a Pane for complex layouts. All sizes and bounds are percentages of available pane space, excluding gutters. Pane props: id, label, defaultSize, minSize (0), maxSize (100), styles and div attributes. Size constraints must admit a total of 100%; impossible constraints throw. Missing defaults share the remaining size and layouts are normalized to the bounds.
SplitPane API
| Prop | Default | Description |
| --- | --- | --- |
| direction | 'horizontal' | Side-by-side panes; 'vertical' stacks them |
| layout / defaultLayout | pane defaults | Controlled or initial percentage sizes |
| onLayoutChange(layout, { source }) | none | Requested or restored layout |
| onResizeStart(layout) | none | Start of a pointer or keyboard resize |
| onResizeEnd(layout, { cancelled }) | none | Completed or canceled resize |
| disabled | false | Disable interactive resizing |
| step | 1 | Keyboard increment in percentage points |
| largeStep | 10 | Shift-key increment in percentage points |
| gutterSize | 8 | Separator width or height in pixels |
| storageKey | none | Opt into persistence under this key |
| storage | window.localStorage | Synchronous getItem/setItem adapter |
| onPersistenceError(error) | none | Invalid stored data or storage failures |
Standard div attributes and styles are supported. Controlled layout requires applying onLayoutChange; defaultLayout initializes internal state only. The wrapper defaults to 100% width and 300px height. Set a definite height for stacked layouts. Pane overflow scrolls independently.
Keyboard And Pointer Controls
Separators expose ARIA orientation, current value and min/max. Left/Right resize side-by-side panes; Up/Down resize stacked panes. Shift uses largeStep; Home/End reach the allowed limits. Pointer moves only affect adjacent panes. Escape, pointer cancellation or window blur restores the drag-start layout. No collapse/expand, pixel bounds, automatic snapping or RTL inversion is included.
Layout Persistence
storageKey opts into localStorage, read after mount for SSR-safe markup. Provide stable pane IDs when persisting. Stored records are accepted only when their IDs, order and direction match; bounds are revalidated. Successful pointer drops, keyboard changes and imperative updates persist; canceled drags do not. storage can provide custom synchronous getItem/setItem; onPersistenceError receives corrupt JSON, storage denial or quota errors. Controlled layouts are not restored automatically. No initial automatic write overwrites an existing record.
Imperative API And Limits
The ref exposes getLayout(), setLayout(percentages) and resetLayout(). The pure helpers normalizeLayout and resizeLayout are exported. Constraint changes normalize rendered sizes; changed pane structure cancels any current drag. The component uses flexbox and does not bundle ResizeObserver or an animation framework. Focus appearance uses native browser outlines.
Support
Support maintenance with a PayPal donation.
Author
Created by Libin Prasanth.
