Introducing PrimeReact v11-alpha 🎉Discover Now

useSplitter

Hook that manages resizable panel layout with keyboard navigation and pointer-based resizing.

Panel 1
Panel 2
basic-demo

Usage#

import { useSplitter } from '@primereact/headless/splitter';
const { rootProps, getPanelProps, getGutterProps, handleProps } = useSplitter({
    panels: [{ minSize: 10 }, { minSize: 10 }],
    defaultSizes: [30, 70]
});
 
<div {...rootProps} style={{ display: 'flex' }}>
    <div {...getPanelProps(0)} />
    <div {...getGutterProps(0)}>
        <div {...handleProps} />
    </div>
    <div {...getPanelProps(1)} />
</div>;

useSplitter manages panel sizing, drag-to-resize, keyboard resizing, and collapse behavior — see Primitive for a component-based API.

Features#

  • Declarative panel config — pass panels with minSize, maxSize, collapsible, and collapsedSize per pane instead of wiring constraints yourself
  • Pointer and keyboard resizing — getGutterProps(index) returns an ARIA separator with drag, arrow key, Home/End, and Enter handlers already attached
  • Horizontal or vertical orientation — one flag switches axis, key mappings, and the data attributes you style against
  • Controlled or uncontrolled sizes — feed sizes + onResize/onResizeEnd for external state or let the hook manage it from defaultSizes
  • Collapsible panes — panels snap to collapsedSize when dragged below their minimum, no extra logic required
  • Resize-in-progress signal — state.resizing plus data-resizing lets you switch cursors and disable selection during a drag

Working with callbacks#

Controlled sizes#

Feed sizes with onResizeEnd (fires after drag completes) or onResize (fires continuously) for external state.

const [sizes, setSizes] = React.useState([50, 50]);
 
const splitter = useSplitter({
    panels: [{ minSize: 10 }, { minSize: 10 }],
    sizes,
    onResizeEnd: (e) => setSizes(e.sizes)
});

Persisting layout across reloads#

Pair onResizeEnd with localStorage to restore the user's layout on next visit.

const [sizes, setSizes] = React.useState(() => JSON.parse(localStorage.getItem('layout') ?? '[30,70]'));
 
useSplitter({
    panels: [{ minSize: 10 }, { minSize: 10 }],
    sizes,
    onResizeEnd: (e) => {
        setSizes(e.sizes);
        localStorage.setItem('layout', JSON.stringify(e.sizes));
    }
});

Collapsible side panel#

Mark a panel collapsible and give it a collapsedSize so dragging below minSize snaps it closed instead of getting stuck.

const splitter = useSplitter({
    panels: [{ minSize: 15, collapsible: true, collapsedSize: 5 }, { minSize: 10 }],
    defaultSizes: [30, 70]
});

Fine-grained keyboard resizing#

Lower step when precise keyboard adjustments matter — the default of 5 moves the gutter 5% per arrow press.

const splitter = useSplitter({
    panels: [{ minSize: 10 }, { minSize: 10 }],
    step: 1
});

Vertical orientation#

orientation: 'vertical' swaps the axis and rebinds arrow keys automatically.

const splitter = useSplitter({
    panels: [{ minSize: 10 }, { minSize: 10 }],
    orientation: 'vertical'
});

Styling with data attributes#

The root exposes data-orientation, data-resizing, and data-disabled so cursor and selection rules can stay in CSS.

[data-orientation='horizontal'][data-resizing] {
    cursor: col-resize;
    user-select: none;
}
[data-orientation='vertical'][data-resizing] {
    cursor: row-resize;
    user-select: none;
}
[data-disabled] {
    pointer-events: none;
    opacity: 0.4;
}

API#

useSplitter#

NameTypeDefault
panelsuseSplitterPanelConfig[]—
Declarative panel configuration array. When provided, the hook auto-registers panels from this config — no `registerPanel` calls needed. Each entry defines constraints for the panel at that index.
sizesnumber[]—
Controlled panel sizes as percentages (must sum to ~100). When provided, the splitter operates in controlled mode — sizes are driven by this prop and should be updated via onResize or onResizeEnd callbacks.
defaultSizesnumber[]—
Default initial panel sizes as percentages (must sum to ~100). Used for uncontrolled mode — sets the initial sizes on mount, after which internal state takes over.
orientation"horizontal" | "vertical"horizontal
Orientation of the panels.
disabledbooleanfalse
When true, disables all resize interactions.
stepnumber5
Step factor to increment/decrement the size of the panels while pressing the arrow keys.
onResizeStart(event: useSplitterResizeEvent) => void—
Callback invoked when resize starts.
onResize(event: useSplitterResizeEvent) => void—
Callback invoked during resize with current panel sizes.
onResizeEnd(event: useSplitterResizeEvent) => void—
Callback invoked when resize ends.
onCollapse(event: useSplitterCollapseEvent) => void—
Callback invoked when a panel collapses or expands.

Accessibility#

Arrow keys resize the panes, Home/End collapse to min/max, and Enter toggles between preset sizes. See Primitive for full WAI-ARIA compliance details.