react-split-pane
A resizable, nestable split-pane React component for building draggable panel layouts.
Repository Health
Technical Analysis
@rexxars/react-split-pane is a maintained fork of the original tomkp/react-split-pane, rebuilt to support React 19 while trimming the API surface down to its essentials. It renders two adjacent panes divided by a draggable resizer, supporting both vertical and horizontal splits that can be nested arbitrarily deep to build complex panel layouts.
The component exposes fine-grained controls over resize behavior — minimum and maximum size constraints (including negative max values for inset boundaries), a fixed step increment for dragging, and callbacks for drag start, drag end, and live size changes — making it a drop-in building block for IDE-style interfaces, admin dashboards, and any layout that needs user-resizable panels.
What You Get
- SplitPane component - a class-based React component rendering two child panes divided by a draggable resizer bar
- Vertical and horizontal splits - switch orientation via the
splitprop, with panes stacking or sitting side-by-side - Nestable layouts - compose multiple SplitPane instances to build multi-panel, IDE-style layouts
- Sizing controls -
minSize,maxSize,defaultSize,size, andstepprops for precise control over resize behavior - Drag lifecycle callbacks -
onDragStarted,onDragFinished, andonChangehooks for persisting or reacting to size changes
Common Use Cases
- Code editor layouts - building IDE-like interfaces with a resizable file tree, editor, and terminal pane
- Admin dashboards - letting users resize a sidebar or detail panel next to a main content area
- Documentation/preview tools - side-by-side markdown editor and live preview panes
- Persisted layout preferences - combining
onChangewith localStorage to remember a user’s preferred pane sizes across sessions
Under The Hood
Architecture
The class-based SplitPane component owns all interaction state (pane1Size/pane2Size, drag position) via React lifecycle methods (componentDidMount, getDerivedStateFromProps, componentWillUnmount) and delegates rendering to two stateless leaf components. Mouse and touch events are normalized into a common shape before size deltas are computed in the drag-move handler, keeping Pane and Resizer as pure, prop-driven views with no internal state of their own. This is a small, single-responsibility architecture — the core component owns all the drag math, so changes there would ripple through its only consumers, but the surface area is narrow enough that this is a reasonable tradeoff for a focused UI primitive.
Tech Stack Written in TypeScript and compiled to dual ESM/CJS output (with generated type declarations) via a Sanity-authored package build tool, with Vite and a React plugin powering the dev server. Tests run through Vitest configured with a real-browser provider (Playwright/Chromium) rather than a DOM emulation library, exercising actual browser layout and event behavior. Linting and formatting are enforced through a shared ESLint config and Prettier, wired into a pre-commit hook, and releases are automated end-to-end through CI using semantic versioning and npm publish with provenance. The package declares React and ReactDOM as peer dependencies across two major versions.
Code Quality The test suite runs in an actual browser rather than a simulated DOM, covering vertical and horizontal split behavior, class name propagation, resize drag callbacks, and a targeted regression test for a StrictMode double-render issue reported by a consumer. Tests are organized into focused spec files with a shared assertion helper that encapsulates DOM queries, keeping individual test cases readable. TypeScript provides type safety across props and state, and CI runs the full suite on every pull request, giving reasonable confidence that changes don’t silently break drag or layout behavior.
API Design
The public API is intentionally narrow — a single SplitPane component with a well-documented set of sizing and styling props, sensible defaults (50px minimum size, vertical split, resizing enabled), and a handful of drag lifecycle callbacks for consumers who need to persist layout state. Getting started requires no configuration beyond installing the package and importing one component. The tradeoff for this simplicity is that it’s a maintained fork of an older, more widely used library, trimmed down and updated for React 19 rather than a new design — ergonomic, but not a novel approach to the problem.