Skip to content

SIG—04 Signature system

Plane

An infinite, zoomable surface for boards, maps and diagrams — inertia, pinch, a minimap and a camera that follows keyboard focus.

Live — this one is real

Drag cards to rearrange. Drag the background to travel, pinch or Ctrl-scroll to zoom, tab between cards and the view follows. Illustrative content.

What worked

Weekly demo kept design and engineering honest about scope.

Rin

Feature flags let support switch off the importer in one click.

Ade

“The staging data finally looked like production.”

QA review

What hurt

The migration plan lived in three documents and nobody owned it.

Tomás

Load tests ran against yesterday's schema.

Mei
Error budget, launch week

Next time

One owner per migration, named in the plan's first line.

Team

Rehearse the rollback, not just the rollout.

Team

Arrow keys move the view, plus and minus zoom, 0 fits everything, 1 returns to 100%. Tab moves between items and the view follows.

Usage

tsx
import { useState } from "react";
import { Plane, PlaneItem } from "mizu-ui";

export function Example() {
  const [notes, setNotes] = useState([
    { id: "a", x: 0, y: 0, text: "Research" },
    { id: "b", x: 260, y: 90, text: "Prototype" },
    { id: "c", x: 90, y: 260, text: "Ship it" },
  ]);
  return (
    <Plane label="Planning board">
      {notes.map((n) => (
        <PlaneItem
          key={n.id}
          id={n.id}
          x={n.x}
          y={n.y}
          width={200}
          label={n.text}
          onMove={(x, y) =>
            setNotes((all) =>
              all.map((a) => (a.id === n.id ? { ...a, x, y } : a)),
            )
          }
        >
          <p
            style={{
              margin: 0,
              padding: 18,
              background: "var(--mizu-ink-2)",
              border: "1px solid var(--mizu-line-bright)",
            }}
          >
            {n.text}
          </p>
        </PlaneItem>
      ))}
    </Plane>
  );
}

This code, running — no configuration beyond the data

Research

Prototype

Ship it

Arrow keys move the view, plus and minus zoom, 0 fits everything, 1 returns to 100%. Tab moves between items and the view follows.

Keyboard

←→↑↓
Travel (Shift for larger steps)
+−
Zoom
0·1
Fit everything · 100%
Tab
Next item — the view follows
←→↑↓
On a draggable item: nudge it (Shift: 48px)
Ctrl+scroll
Zoom at the pointer; double-click zooms in

Source & setup

Add this component to your project with the shadcn CLI. The command copies its source and styles into your configured UI directory.

sh
npx shadcn@latest add 0xuser64bit/mizu/plane

For npm imports, import mizu-ui/styles.css once. Fonts are optional via mizu-ui/fonts.css. Override --mizu-* tokens or use className for local styling. Requires React and Motion.

Inspect signature/Plane.tsx

Source is included in the npm package under src/signature/Plane.tsx.

Open full source ↗

Props

PropTypeDefaultDescription
label / childrenstring / ReactNode—Accessible name and world content (usually PlaneItems).
view / defaultView / onViewChange{ x, y, zoom }—Camera: the world point at the centre and the zoom. Frames the content by default.
minZoom / maxZoomnumber0.15 / 4Zoom limits.
grid / minimap / coordinates"dots" | "lines" | "none" / boolean / boolean"dots" / true / trueSurface texture and instruments.
toolsReactNode—Extra toolbar controls beside zoom and Fit.
refPlaneHandle—fit(), zoomBy(factor), flyTo(box | point) and toWorld(clientX, clientY).
PlaneItem: id / x / y / width / height / labelstring / number—World position and size; measured when width or height is omitted.
PlaneItem: onMove / onMoveEnd(x, y) => void—Makes the item draggable and nudgeable.

Accessibility

The viewport is a focusable canvas group with keyboard travel and zoom. Items are named groups in reading order; tabbing to one flies the camera to it. Draggable items nudge with arrow keys. Plain scrolling only pans once the canvas is active, so the page never traps the wheel; a hint explains Ctrl-scroll.

Motion

The camera glides in log space and pulls back on long flights before settling in; drags coast to rest with inertia. The zoom-adaptive dot grid re-densifies as you scale. Reduced motion jumps directly and removes coasting.

Works alongside