Resizing
Users resize panes by dragging the dividers between them. The resize prop on
Mosaic controls how that works. Every option is optional, and leaving resize
out keeps the defaults.
<Mosaic
resize={{
minimumPaneSizePercentage: 10,
minimumPaneSizePx: { column: 30 },
renderSplitHandle: (direction) => <Grip direction={direction} />,
preview: true,
}}
renderTile={/* ... */}
initialValue={/* ... */}
/>
To turn resizing off completely, pass resize="DISABLED". The dividers are
then not rendered at all.
Try it
This layout keeps panes at least 80px wide or tall, shows a grip on every divider, and only moves the divider while you drag. The panes resize when you let go.
function ResizingExample() { const grip = (direction) => ( <span style={{ width: direction === 'row' ? 4 : 28, height: direction === 'row' ? 28 : 4, borderRadius: 2, background: '#8f99a8', }} /> ); return ( <div className="live-mosaic-frame"> <Mosaic resize={{ minimumPaneSizePx: 80, renderSplitHandle: grip, preview: true, }} renderTile={(id, path) => ( <MosaicWindow path={path} title={`Panel ${id}`}> <div style={{ padding: 20 }}>Panel {id}</div> </MosaicWindow> )} initialValue={{ type: 'split', direction: 'row', children: [ 'a', { type: 'split', direction: 'column', children: ['b', 'c'] }, ], }} /> </div> ); }
Minimum pane size
Two options limit how small a pane can get. Both apply at the same time and the larger one wins.
minimumPaneSizePercentageis a percentage of the split the pane is in. Default:10.minimumPaneSizePxis the visible size of the tile in pixels. The 6px gutter around each tile is added for you. Default:0.
Either one also takes { row, column } to use different values per split
direction. row splits put panes side by side, column splits stack them. For
example, to let side-by-side panes shrink all the way while stacked panes keep
room for a 30px title bar:
<Mosaic
resize={{
minimumPaneSizePercentage: { row: 0, column: 0 },
minimumPaneSizePx: { column: 30 },
}}
// ...
/>
A direction you leave out of the object falls back to the default. The minimums apply to the two panes next to the divider you drag, not to panes nested inside them: dragging a divider can still squeeze a nested split's panes below the minimum. They also only apply while dragging. They don't change a layout you pass in, and they aren't re-applied when the container itself gets smaller.
Custom divider handles
renderSplitHandle(direction) renders your content centered on every divider,
inside a .mosaic-split-handle element. Pressing it drags the divider like the
rest of the bar, and the divider keeps its position relative to where you
grabbed it, so a wide grip doesn't jump to the cursor. Use direction to draw a
vertical grip on row dividers and a horizontal one on column dividers.
Dividers with a handle are stacked above tile content, including the window toolbar and the drop targets shown while dragging a window, so a grip that is larger than the 6px bar covers whatever is under it. Outer dividers stack above inner ones so their grips stay grabbable where dividers meet. That ordering goes eight levels deep; below that, dividers share the same level and a nested one can cover an outer grip.
Preview while dragging
By default the panes resize live, and onChange fires as the divider moves.
With preview: true, only the divider moves while dragging. It gets a
-preview class and the same look as on hover. The panes resize once, when the
divider is released, so onChange and onRelease fire a single time per drag.
That helps when tiles are expensive to re-render.
While any divider is being dragged, the tiles don't receive pointer events, so iframes and other apps inside them can't interrupt the drag.