Skip to content

Advanced Zoom Options

useSplitView is built on top of useZoomPinch, which supports inertia, bounds, keyboard navigation, rotation, double-tap, snap-to-grid, activation keys, and more. Starting with use-split-view@0.3.0, you can forward any of those options to the underlying instance via the zoom option — without losing the split-view wiring (container, scale limits, view state, and the drag-handle lock stay intact).

zoom is a pass-through: every field is forwarded to the underlying useZoomPinch call, except the ones useSplitView already owns (containerRef, minScale/maxScale, panSpeed/zoomSpeed, viewState/onViewStateChange, enabled).

const sv = useSplitView({
direction: "horizontal",
zoom: {
// any UseZoomPinchOptions field (minus owned ones) goes here
},
})

Keep the content from drifting out of the viewport:

useSplitView({
zoom: {
bounds: {
minX: -500,
maxX: 500,
minY: -300,
maxY: 300,
mode: "bounce",
bounceFactor: 0.3,
},
},
})

Let the content glide to a stop after the user releases a drag:

useSplitView({
zoom: {
inertia: { enabled: true, friction: 0.9 },
},
})

Lower friction (closer to 0) stops sooner; higher (closer to 1) glides further.

Make the container focusable (tabIndex={0}) and pan/zoom with the arrow keys, +/-, etc.:

const sv = useSplitView({
zoom: { keyboard: { enabled: true, panStep: 40, zoomStep: 1.5 } },
})
<div ref={sv.containerRef} tabIndex={0}>...</div>
useSplitView({
zoom: {
doubleTap: { enabled: true, mode: "toggle", step: 2 },
},
})

mode can be "zoomIn", "reset", or "toggle" (toggles between fit and step× zoom).

Enable two-finger rotation and constrain the angle:

useSplitView({
zoom: {
gestures: { rotate: true },
rotation: { snapLevels: [0, 90, 180, 270] },
},
})

Snap the pan position to a grid of content-space pixels:

useSplitView({
zoom: { snapToGrid: { size: 32, mode: "end" } },
})

Require a modifier key for specific gestures — e.g. only pan while holding Space-like behavior, or zoom only with Alt:

useSplitView({
zoom: {
activationKeys: { zoom: "Alt" },
},
})

Toggle gesture families or lock panning to a single axis:

useSplitView({
zoom: {
gestures: { pan: true, zoom: true, rotate: false },
axis: "x",
wheelMode: "zoom",
},
})

React to gesture boundaries for analytics, lazy loading, or UI feedback:

useSplitView({
zoom: {
onPanStart: (view) => console.log("pan start", view),
onZoomEnd: (view) => console.log("zoom end", view),
onTransformEnd: (view) => saveView(view),
},
})

Everything useSplitView exposes still works alongside zoomsplit, handleProps, getPaneState, setNaturalSize, zoomApi, and the isLocked behavior from the drag handle all keep working. The zoom object only adds capabilities; it doesn’t rewire the split.