Minimap
<Navigator /> adds a mini-map next to a scrollable paper. It shows a bird's-eye overview of the diagram and a viewport rectangle that tracks the main canvas. Dragging the rectangle pans the canvas; the rectangle's footprint inside the overview tells the reader where they are at a glance.
Reach for it when the diagram outgrows the visible area and your users need to keep their bearings. <Navigator> requires the target paper to live inside a <PaperScroller>: it reads the scroll position and zoom bounds straight from it. See Zoom & Scroll for the surrounding scroll model.
A navigable bird's-eye view​
The demo spreads a connected workflow across a canvas larger than the viewport. A floating toolbar (top-left) drives the view: zoom buttons, a Links toggle, and a link-color picker, while a <Navigator> mini-map (bottom-left) shows the bird's-eye overview. Drag the blank canvas to pan and watch the viewport rectangle track along; drag the rectangle to pan back; drag its corner handle (or use the toolbar − / +) to zoom; click anywhere in the overview to jump there; toggle the links and recolor them to see the overview restyle live.
<Navigator> reads the scroll position and zoom bounds from the <PaperScroller>, so it renders happily outside the scroller's subtree, pinned to a corner. The toolbar sits outside that subtree as well, yet its hooks (usePaperScroller() and usePaperScrollerViewport(), which drive the − / + buttons and the live %) use the no-arg form; they resolve the single paper automatically, so no id is needed.
Omit paper to use the single default paper. Pass a paper id or ref to target a specific paper when your app renders more than one.
The link-color picker is data-driven too: it calls useGraph().updateCells(...) to set each link's data.color (filtered with isLink), and the overview re-renders on its own because the link view watches each cell's data (see Styling elements and links).
This demo wraps the diagram in <Diagram>, so Built-in interactions wire blank-drag pan and wheel/pinch zoom to the <PaperScroller> automatically, with no manual gesture wiring. The mini-map tracks the viewport no matter how the pan or zoom is triggered.
Interaction​
The mini-map exposes these direct gestures:
- Click outside the viewport rectangle: jumps the main canvas to that point.
- Drag the viewport rectangle: pans the canvas.
- Drag the rectangle's corner handle: resizes the rectangle to zoom in or out (only when
zoomis enabled).
Styling elements and links​
By default the mini-map paints every element as a thin black rectangle outline and every link as a thin black line. Pass elementStyle and linkStyle to restyle either layer; each receives a payload and returns SVG attributes:
elementStyle({ record, model, width, height }):<path>attributes for the element's outline (fill,stroke,strokeWidth,opacity, and so on).linkStyle({ record, model }):<path>attributes for the link (stroke,strokeWidth,strokeDasharray,opacity, and so on).
In both, record is the cell's typed React record (read your fields off record.data) and model is the underlying dia.Element / dia.Link for imperative cell state; elementStyle also hands you the element's width / height.
<Navigator<TaskData, LinkData>
elementStyle={({ record }) => ({ fill: record.data.color })}
linkStyle={({ record }) => ({ stroke: record.data.color, strokeWidth: 4 })}
/>
Passing generics (Navigator<TaskData, LinkData>) gives record.data full type inference inside both callbacks. The mini-map also inherits the main paper's routing, connector, and anchors, so link paths follow the same shape they have on the canvas; the demo's orthogonal routing shows up orthogonal in the overview too.
Because both callbacks read from each cell's data, you can restyle the overview reactively by updating that data. The demo's color picker does exactly this: useGraph().updateCells sets every link's data.color, and the overview repaints because the link view watches each cell's data:
const { updateCells, isLink } = useGraph();
function recolorLinks(color: string) {
updateCells((cells) =>
cells.map((cell) =>
isLink(cell) ? { ...cell, data: { ...cell.data, color } } : cell
)
);
}
Showing or hiding links​
showLinks is on by default. Set it to false when the link layer is too busy at mini-map scale and only the element layout matters:
<Navigator showLinks={false} />
Drag-to-zoom​
Set zoom to true to let users resize the viewport rectangle from its corners: pulling outward zooms out, pulling inward zooms in. The min and max bounds come straight from the parent <PaperScroller> (its minZoom / maxZoom props), so the two stay consistent:
<Navigator zoom />
The demo enables zoom, so the corner handle and the toolbar − / + buttons offer two routes to the same scroller zoom.
Viewport behavior​
dynamicZoom (default true) keeps the mini-map fitted to the content as the main paper grows or shrinks, so the whole diagram stays in view. Set it to false to hold a fixed overview instead:
<Navigator dynamicZoom={false} />
padding (default 10) controls the breathing room inside the mini-map; bump it up when the content sits too close to the edges:
<Navigator padding={20} />
useContentBBox (default true) measures the visible-area rectangle from the content's bounding box, ignoring CSS-driven element sizes. Leave it on for most diagrams; set it to false to derive the overview from the paper's box instead:
<Navigator useContentBBox={false} />