Componentsv2.189.1
Iconsv1.19.0
MCPv0.8.62
Tokensv0.34.3

A layout component for splitting a space into resizable, nestable panes with draggable handles.

SplitView lays out resizable panes along one axis. Place a SplitViewResizer between two SplitViewPanes to make that boundary draggable. Nest a SplitView inside a pane for two-dimensional (columns and rows) layouts.

The group must have a height for the panes to fill — set one on the SplitView (or a parent).

Importing

import { SplitView, SplitViewPane, SplitViewResizer } from '@customerio/pluma-components/react';

Basic usage

A two-pane split with a draggable boundary. defaultSizes seeds the flexible panes' percentages; drag the handle to resize.

Loading editor

Orientation

orientation="vertical" splits into stacked, resizable rows.

Loading editor

Two-dimensional layouts

Nest a vertical SplitView inside a pane of a horizontal one to get resizable columns and rows.

Loading editor

Flexible and fixed panes

A pane's size is interpreted by unit: a percentage ('30', '30%') is a flexible pane that shares leftover space, while a pixel length (120, '120px', '12rem') is a fixed track that keeps its width as the container resizes. Set isResizable={false} on a fixed pane and omit the resizer beside it to keep it static.

Loading editor

Minimum and maximum sizes

Constrain how far a pane can be resized with minSize / maxSize (pixels or percentages).

Loading editor

Hiding panes

Set isHidden to collapse a pane to zero and let the remaining panes take its space; the pane stays mounted and restores its size when shown again. Deciding when to hide (and rendering any toggle affordance) is up to you.

Loading editor

Snapping

snaps are percentages the boundary is pinned to. When set, dragging a resizer moves discretely between these points (snapping to the nearest one) instead of resizing smoothly — useful for offering a few preset splits.

Loading editor

Persisting sizes

SplitView is uncontrolled by default. To persist a user's layout, read the sizes from onResizeEnd (fired once a drag or keyboard change is committed) and store them, then pass them back as defaultSizes. For full control, pass sizes and update it from onSizesChange.

useStoredSplitView

The useStoredSplitView hook wires that persistence up for you. Give it an id and spread the result onto the SplitView — the layout is saved to localStorage on resize and restored on the next load. Resize the example below and reload the page: it comes back the way you left it.

Loading editor

Custom storage — by default the hook uses localStorage (falling back to a no-op when it's unavailable, e.g. during server rendering). Pass a storage object ({ getItem, setItem }) to persist somewhere else — cookies for SSR, or an in-memory stub for tests.

Conditional panels

When panels are shown and hidden, give each SplitViewPane a stable id and pass the currently visible ids as panelIds. Each configuration then remembers its own layout, and the split re-applies the stored layout for whichever configuration is active — no remounting required. Resize a boundary, toggle the preview off and on, and the layout comes back.

Loading editor

Accessibility

Each SplitViewResizer is a role="separator" with aria-orientation and aria-valuenow/aria-valuemin/aria-valuemax. It is keyboard-operable: focus the handle and use the arrow keys to resize (hold Shift for a coarser step), following the WAI-ARIA window splitter pattern. When snaps is set, the arrow keys move between the snap points instead (Shift / Home / End jump to the ends).

API

Initial percentages for the flexible panes, in DOM order, for the uncontrolled case. When omitted, flexible panes split the available space equally.

Default:true

Disables resizing for the entire split. Panes still reflow when hidden.

Fires continuously while a resizer is being dragged, with the live pane percentages.

Fires once a resize gesture is committed (pointer up / keyboard change). Use this to persist a user's layout.

Fires when the layout changes in the controlled case. Mirror of sizes.

Default:'horizontal'

The axis panes are laid out and resized along. horizontal splits into columns, vertical splits into rows.

Controlled percentages for the flexible panes, in DOM order. When provided the consumer owns the layout and must update it from onSizesChange.

Snap points, as percentages of the flexible space. When set, dragging a resizer moves the boundary discretely between these points (the nearest one to the pointer) rather than resizing smoothly.

Initial size for the uncontrolled case. See SplitViewPaneSize.

A stable identity for the pane. Used to remember a pane's size across renders and, with useStoredSplitView, to key persisted layouts. Give conditionally-rendered panes an explicit id so each configuration is tracked and restored independently; when omitted, an automatic id is generated. In React it is also forwarded as the element's id.

Default:false

When true, the pane collapses to zero and the remaining panes take its space. The pane stays mounted. Toggling this is the consumer's responsibility.

Default:true

When false, this pane keeps its size and its adjacent resizers are inert.

Maximum size this pane may be resized to. Pixels (number / '200px') or percentage ('20%').

Minimum size this pane may be resized to. Pixels (number / '200px') or percentage ('20%').

Controlled size. See SplitViewPaneSize for how units are interpreted. A fixed (pixel) size makes this a non-flexing track.

Default:false

Disables this specific resizer.

Default:true

Renders a visible grip affordance in the center of the resizer.