Region callbacks (kept fresh across renders).
Optionaloptions: MouseRegionOptions
Optional regionId (defaults to an auto-generated
unique id — pass one to control identity, e.g. for
drag/hover bookkeeping), explicit layerId override,
hit-test priority (higher wins on overlap; defaults
0), clickOnFocus (whether a click forwards keyboard
focus to the region's bound focusId; defaults true),
clickOnRise / dragOnRise / wheelOnRise /
enterOnRise (whether the matching mouse gesture
raises the surrounding regular layer to the top;
defaults false), leaveOffRise (whether a hover
leave restores the layer's initial zIndex; only applies
when enterOnRise is set; defaults true),
enterOnFocus (whether a hover enter forwards focus;
defaults false), leaveOffFocus (whether a hover
leave clears the focus; only applies when
enterOnFocus is set; defaults true), and ref
(an object ref to register the region under instead of a
hook-created one — share it with boundKeyboard for
focus forwarding).
A ref to attach to the Ink <Box> to track.
Click, wheel, hover, and drag callbacks:
const boxRef = useMouseRegion({
onClick: (event, rect) => {
const col = event.x - rect.x - 1; // local cell column (1-cell border)
console.log(`Clicked cell ${col} at ${event.x},${event.y}`);
},
onWheel: (event) => {
if (event.button === 'wheel-up') scrollUp();
if (event.button === 'wheel-down') scrollDown();
},
onEnter: () => setIsHovered(true),
onLeave: () => setIsHovered(false),
onDragStart: () => setIsDragging(true),
onDragMove: (event) => moveTo(event.x, event.y),
onDragEnd: () => setIsDragging(false),
});
return <Box ref={boxRef}>…</Box>;
Register an Ink element as a mouse region.
Attach the returned ref to a
<Box>. The engine hit-tests xterm-mouse events against the element's measured rectangle and fires the callbacks:onClickfor clicks,onWheelfor wheel events,onEnter/onLeavefor hover transitions, andonDragStart/onDragMove/onDragEndfor the drag lifecycle.Clicks and drags are exclusive. A press inside the region arms a drag capture on the pressed region — the drag keeps firing even when the cursor leaves the region — and the first
dragevent promotes the press to a drag, firingonDragStartand thenonDragMove.onDragEndfires on release only when a real drag happened; a plain click firesonClickinstead and never touches the drag callbacks.The region is attributed to the surrounding layer/modal layer automatically (same layer scoping as useKeyboard); outside any layer it registers on the shared root layer, hit-tested last. While a modal layer is open it takes over hit-testing exactly like keyboard modal priority — events that miss the modal do not fall through to layers or root regions, so clicking "through" a modal can never trigger the UI underneath.
The rect is re-measured and re-registered on every render and on every Ink layout commit, so the hit area stays in sync with the terminal whether the window resizes, content grows, or an ancestor moves (e.g. a draggable modal frame relocating its children) — no re-render of the tracked component required. This covers elements whose absolute position moves while their own relative metrics don't change (a button inside a fixed-width centered menu row, a child control inside a moved frame).
Hit priority follows keyboard semantics: modal layers → regular layers → root regions; within a layer, later registration wins unless
priorityoverrides. Use a higherpriorityfor child controls (e.g. a button inside a panel): React mounts children before parents, so the child would otherwise register first and lose overlap resolution.Must be used inside a KeyboardProvider with
mouseenabled.When a
boundKeyboardcall registers this same ref with afocusId(e.g.boundKeyboard(['a'], fn, { ref, focusId })), clicking the region forwards keyboard focus to that focusId before the user's ownonClickruns — so a mouse click and a keyboard press converge on the same focus target, and the component can react via useFocusState. Focus forwarding is enabled by default; passclickOnFocus: falseto keep clicks purely on the mouse callbacks.Hover can drive focus too: with
enterOnFocus: truethe region's focusId is activated on mouse enter, and deactivated on leave (viakickFocusGroup) — unlessleaveOffFocus: falsekeeps it. NoteleaveOffFocusonly takes effect whenenterOnFocusis set, so a click-only region never loses focus by the cursor leaving it.With
clickOnRise: true, clicking the region also raises the surrounding regular layer above all other layers (seebringLayerToFront) before the user's ownonClickruns. Modal layers are unaffected — while a modal is open it owns all mouse hit-testing, and regular layers never rise above modals — and regions outside any layer do nothing.