Component

Infinite Canvas

A pan/zoom viewport foundation for whiteboard, system-design, and goal-graph surfaces. Renders a clipped container that applies a CSS transform to a content layer — other canvas components render into it with absolute positioning.

Basic with grid

An uncontrolled canvas with a dot-grid background. Scroll to zoom, drag to pan.

Canvas node

Scroll to zoom · Drag to pan

Another node

Zoom controls

Pass showControls to add an overlay with + / − / fit buttons.

Use +/− buttons

or scroll to zoom

Fit to content

Provide contentBounds and the ⊞ button fits and centers the canvas on those bounds.

Fit target A

Fit target B

Fit target C

Press ⊞ to fit all nodes

Installation

$pnpm add @refraction-ui/react

Usage

tsx
import { InfiniteCanvas } from '@refraction-ui/react'

export function MyBoard() {
  return (
    <div style={{ width: '100%', height: '100vh' }}>
      <InfiniteCanvas showGrid showControls className="w-full h-full">
        {/* render nodes with absolute positioning */}
        <div className="absolute top-8 left-8 rounded border p-4">Node A</div>
        <div className="absolute top-8 left-64 rounded border p-4">Node B</div>
      </InfiniteCanvas>
    </div>
  )
}

Props

PropTypeDefaultDescription
zoomnumber--Controlled zoom level (1 = 100 %).
xnumber--Controlled pan offset on the x-axis (pixels).
ynumber--Controlled pan offset on the y-axis (pixels).
panbooleantrueEnable pointer-drag-to-pan in uncontrolled mode.
minZoomnumber0.25Minimum zoom level.
maxZoomnumber4Maximum zoom level.
showGridbooleanfalseShow a dot-grid background using the border semantic token.
showControlsbooleanfalseShow zoom-controls overlay (+, −, fit).
onTransformChange(transform: CanvasTransform) => void--Called whenever the pan/zoom transform changes.
contentBoundsBounds--Axis-aligned bounding box of canvas content used by the fit control.
classNamestring--Additional CSS classes (typically w-full h-full).