Splitter

Panels the reader can resize by dragging the bar between them, with per panel minimums, maximums and a collapse control.

Usage

Panels people resize by dragging the bar between them, each with its own minimum, maximum and optional collapse. First decide whether the split should move at all.

When to use

Splitter lets people resize panels by dragging the bar between them. Use it when the right proportion is theirs to choose, and they will change it more than once: a file tree beside an editor, a list beside a detail pane, a form beside a live preview.
  • Use Layout.Sider when one side is navigation at a width you already chose. It has the collapse behavior and breakpoints a nav needs.
  • Use Row and Col when the split does not need to move. A grid needs no height and reflows at your breakpoints.
  • Use a Drawer or a Modal when the second pane is opened, read and closed.
  • Use Collapse or Tabs when only one region is read at a time.
On small screens there is no room to trade and the bar is a small touch target. Show one pane at a time there instead.

Horizontal or vertical

orientation takes horizontal (the default, panels side by side) or vertical (panels stacked). The vertical boolean also works, and layout is the old name and logs a warning.
  • Horizontal suits two things used together, like source and preview or list and detail.
  • Vertical suits a main surface over a secondary one, like a canvas over a console. Height is scarcer, so keep the lower pane useful at its minimum.
  • The collapse buttons follow the axis: left and right chevrons from your icon pack on a horizontal Splitter, which mirror in right-to-left layouts, and up and down on a vertical one.

Panels, and how wide they get to be

Each region is a Splitter.Panel, and there is a bar between each pair. Two panels have one bar, four have three.
  • defaultSize sets the starting size. size controls it, and needs the new value written back from onResize. Both take pixels or a percentage.
  • min and max limit the drag. Set min to the smallest width where the pane is still useful, not the smallest where it still renders.
  • resizable={false} locks a panel, and the bars on both sides of it stop moving. In a three-panel layout that can freeze more than you expect.
  • A panel collapsed to zero that also has a min loses its bar, since there is nothing left to drag. Use collapsible for a panel that folds away.
Do not mix the two modes. A size on one panel beside a defaultSize on another makes the panel snap back on release. Give every panel a size, or every panel a defaultSize.

Collapsing a panel

Two different props are called collapsible.
  • On the Splitter it is { motion, icon }: whether collapsing animates, and which icons the buttons use. It does not turn collapsing on.
  • On a Panel it is boolean | { start, end, showCollapsibleIcon }: which way that panel can collapse, and when its buttons show. The buttons only appear on a panel that sets it.
showCollapsibleIcon defaults to "auto", which shows the button when the bar is hovered or focused, and always on touch devices. true always shows it. false removes it, and with it the only keyboard way to collapse the panel.
A collapsed panel remembers its size, so the same button restores it. A panel dragged to zero does not. collapsible.motion is off by default. Turn it on for a smooth fold, unless the panel's content is heavy to reflow.

Nesting splitters

A Splitter can go inside a Panel. A nested one running the other way gives three regions, like a sidebar beside an editor over a console. Each level resizes on its own.
  • Alternate the axes. Two nested splitters on the same axis give two bars that look alike and do different things.
  • Stop at two levels. Each extra level adds sizes to save and restore.
  • A panel holding a nested Splitter does not scroll itself, so the inner one owns scrolling and you never get two scrollbars on one edge.

Reacting to a resize, and keeping the split

Three callbacks receive the panel sizes: onResizeStart when a drag starts, onResize on every move and onResizeEnd when it ends.
  • Use onResize for controlled sizes, which have to update on every move.
  • Use onResizeEnd for anything expensive, like saving to localStorage or a preferences request. Saving from onResize writes on every frame of every drag.
  • lazy resizes only when the drag ends and shows a preview line meanwhile. Use it when the panels are costly to lay out again, at the cost of a live preview.
  • onDraggerDoubleClick is a good place for a reset to the starting sizes. It receives the bar's index.
Save the split per screen, since a file browser and a settings page want different proportions. Restore it as defaultSize and check it against min and max first, because a size saved on a wide monitor can be below the minimum on a laptop.

Height, and what a panel does with its overflow

Splitter has no height of its own, so inside a parent with an automatic height it collapses to nothing and shows a blank gap. Give it a height: a class on the root, a fixed value, or a parent with a set height.
  • Each panel scrolls its own content and the bars stay put, so do not size content inside a panel against the viewport.
  • Put padding on your content, not on the panel, or the scrollbar sits inside the padding.
  • Content that cannot shrink, like a wide table, scrolls sideways once the panel gets narrower. Choose between that scrollbar and a min.
  • A position: sticky header inside a panel sticks to the panel, not the page, since the panel is what scrolls.