v0.1.0 — open source on npm

Build IDE-grade layouts for React.

Headless, resizable, tabbed panel splits. No imposed styles — you own every pixel. Ship complex multi-panel UIs in hours, not weeks.

$npm install react-splitkit

Why react-splitkit

Everything you need to build panel-based apps.

Infinitely composable

Nest horizontal and vertical splits as deep as you need. The layout tree is plain data — serialise it to JSON and restore it later.

Headless by design

Zero imposed styles. You own every pixel — use Tailwind, CSS Modules, or plain CSS. The library wires up behaviour, you bring the look.

Full tab management

Add, close, reorder, and drag tabs between panels. A registry maps tab types to render functions so your tabs are declarative and type-safe.

TypeScript-first

Every hook, component, and registry entry is fully typed. Autocomplete works end to end — from createSplit all the way into your render functions.

Programmatic control

usePanel gives you split, collapse, maximize, and close from any component. Build your own panel chrome with full control over every action.

Lightweight

No heavy dependencies. Zustand handles layout state. No CSS frameworks required at runtime — you bring everything, the library wires it up.

Simple API

Describe the layout.
We handle the rest.

Define your layout as plain data with createSplit and createPanel. Map tab types to render functions in a registry. Wrap with LayoutProvider and you're done.

  • No CSS required at runtime
  • Full drag-to-resize out of the box
  • Keyboard accessible tab navigation
  • Persist and restore layout from JSON
App.tsx
import { createSplit, createPanel, LayoutProvider, LayoutRoot } from 'react-splitkit';
const layout = createSplit('root', 'horizontal', [
createPanel('left', [{ id: 'a', tabType: 'editor' }]),
createPanel('right', [{ id: 'b', tabType: 'preview' }]),
]);
const registry = {
editor: { tabType: 'editor', render: () => <Editor /> },
preview: { tabType: 'preview', render: () => <Preview /> },
};
export default function App() {
return (
<LayoutProvider initialLayout={layout} registry={registry}>
<LayoutRoot renderPanel={({ panel }) => <Panel panel={panel} />} />
</LayoutProvider>
);
}

Comparison

How it compares.

react-splitkit is the right pick when you need tabs, runtime splitting, and a fully serializable layout. For pure resize-only use cases, react-resizable-panels is a mature alternative.

Featurereact-splitkitNEWreact-resizable-panelsallotment
Fully headless (zero CSS)Partial1
Resizable panels
Tabbed panels
Split panels at runtime
Collapse & MaximizePartial2
Serializable JSON layoutPartial3
Multiple independent layouts
Full keyboard + ARIAPartial4Partial4
TypeScript-first
  1. 1Requires minimal CSS for layout mechanics to function — no visual opinions, but not fully zero-CSS.
  2. 2Has a collapsible prop but no maximize.
  3. 3onLayout saves panel sizes only — the full panel tree structure is defined in JSX, not serializable.
  4. 4Basic keyboard support; missing roving tabindex and full aria-value* attributes on resizers.

Note: react-splitkit is newly released. The core is working and the API is stable, but as with any early-stage library you may encounter rough edges. If you run into anything unexpected, please open an issue — it helps a lot.

FAQ

Frequently asked questions

Everything you need to know about react-splitkit's capabilities — customisation, accessibility, persistence, and SSR support.

Yes — completely. react-splitkit is fully headless: it ships zero CSS and no opinionated markup. You pass renderPanel and renderTab functions and return whatever JSX you want. The library only owns state, ARIA, keyboard handlers, and resize math — Tailwind, CSS Modules, or plain CSS, your choice.

Ready to build?

Read the docs and ship your first panel layout in under 5 minutes.