KQ-2126 · ZOOM/READOUT

Zoom Readout

The top strip of a whiteboard over the board it drives: the active tool sits on a marker that slides between tools on springs.snap, and the zoom readout is an odometer whose digits are separate wheels — a step turns only the wheels whose digit changed, the short way in the direction the zoom moved, with snap's one crisp overshoot, while fit to selection turns them on springs.glide in the same frame as the fit icon's brackets close on its centre and four brackets on the board converge onto the rectangle the selection glides into. A trackpad pinch follows the fingers 1:1 about the pointer and the hand tool drags the board 1:1 and coasts to its projected rest on glide; V, H and 1–8 pick tools, Cmd or Ctrl with = and − step the zoom, Shift+1 fits, and below 36rem the tools fold into one menu.

KQ-2126 · ZOOM/READOUT

Fernworks / Q4 launch board

V, H or 1–8 pick a tool · ⌘ or Ctrl with = and − zoom · ⇧1 fits

Select · 50% · 1 selected · fit ready

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/zoom-readout

Props

ref
React.Ref<ZoomReadoutHandle>
default —
Imperative handle with fit(target?) and zoomTo(zoom), for hosts that drive the board from elsewhere.
tools
ZoomReadoutTool[]
default defaultZoomReadoutTools
The tools in the strip, in order: { id, label, icon, key? }. The key is a single-letter shortcut; 1–9 always pick by position.
tool / defaultTool
string
default "select"
The active tool id, controlled or initial. The hand tool makes the whole board a pan surface.
onToolChange
(tool: string) => void
default —
Fires from the press, menu choice or key that picked a tool.
zoom / defaultZoom
number
default 50
Zoom in whole percent, controlled or initial. A controlled change the host refuses never moves the board.
onZoomChange
(zoom: number) => void
default —
Fires with the new whole-percent zoom from the step, preset, pinch or fit that changed it.
minZoom
number
default 10
Lowest zoom, percent.
maxZoom
number
default 800
Highest zoom, percent. Its digit count sets how many wheels the readout has.
presets
number[]
default [10, 25, 50, 75, 100, 150, 200, 400, 800]
The stops Zoom in and Zoom out step through, also listed in the readout's menu.
items
ZoomReadoutItem[]
default defaultZoomReadoutItems
What is on the board, in board pixels: { id, kind: "frame" | "sticky" | "shape" | "ellipse" | "text", x, y, w, h, label, note?, tone? }.
selection / defaultSelection
string[]
default ["pricing"]
Selected item ids, controlled or initial. Fit selection is aria-disabled, with the reason in its name, while this is empty.
onSelectionChange
(ids: string[]) => void
default —
Fires from the click, key or Escape that changed the selection.
onFit
(fit: { target: "selection" | "all"; zoom: number; ids: string[] }) => void
default —
Fires when a fit runs, with what was fitted and the zoom it landed on.
fitPadding
number
default 20
Screen pixels left around a fitted selection.
toolSize
number
default 32
Tool and zoom button size in px. The strip is 12 px taller and the readout's type scales with it.
readoutStyle
"roll" | "tiles" | "meter"
default "roll"
How the zoom reads: bare rolling digits, each digit on a split tile like a counter, or digits over a level meter that fills on a log scale between minZoom and maxZoom.
accent
"cobalt" | "plum" | "mint" | "ink" | string
default "cobalt"
Tool marker, selection outline, fit brackets and meter: a named accent or any CSS colour.
title
string
default "Q4 launch board"
The board's name, shown from 40rem; with the workspace it is the piece's accessible name.
workspace
string
default "Fernworks"
The workspace the board belongs to; its initial is the monogram.
viewportHeight
number
default 164
Height of the board viewport under the strip, px. Menus open inside it.
shortcuts
boolean
default true
Listen for tool letters, 1–9, Cmd or Ctrl with = − 0, Shift+1, Shift+0 and Escape while focus is inside the piece.
status
"ready" | "loading" | "error"
default "ready"
Board state: loading draws a still skeleton (it pulses only when motion is allowed), error offers Retry. Fit is off in both.
onRetry
() => void
default —
Called by the error state's Retry button.
disabled
boolean
default false
Turns every control and the board off.
className
string
default —
Classes for the outer section.