Skip to content

fix(canvas): block browser pinch-zoom inside breakpoint frame iframes#65

Draft
DavidBabinec wants to merge 1 commit into
mainfrom
fix/canvas-iframe-pinch-zoom
Draft

fix(canvas): block browser pinch-zoom inside breakpoint frame iframes#65
DavidBabinec wants to merge 1 commit into
mainfrom
fix/canvas-iframe-pinch-zoom

Conversation

@DavidBabinec

Copy link
Copy Markdown
Contributor

Symptom

Hovering a breakpoint frame's toolbar (e.g. Switch to Tablet breakpoint) and pinch-zooming out on a trackpad zooms the entire admin page — which is supposed to be locked.

Root cause

AdminZoomGuard cancels pinch / ctrl-wheel / Safari gesture* browser zoom, but it's installed only on the parent admin document (main.tsx). Each canvas breakpoint frame renders inside its own iframe document, and wheel/gesture events that originate inside an iframe never cross the boundary to the parent — so the parent guard never sees them.

The design frame had an ad-hoc wheel forwarder (IframeFrameSurface) that happened to preventDefault() wheel events (to drive canvas pan), which masked the issue for plain ctrl-wheel in Chrome — but it never handled gesturestart/gesturechange or multi-touch pinch, and live-preview frames have no forwarder at all. So pinch over a frame escaped to the browser and zoomed the page.

Fix

Install the existing installAdminZoomGuard inside every frame document (design and live), where IframeFrameSurface already owns iframeDoc. The wheel forwarder still routes pan/zoom to the canvas; the guard only cancels the browser's native zoom default. One small effect, reusing the shared guard — no new mechanism.

Verification

  • bun run build ✓ · bun run lint ✓ · bun test ✓ — 5436 pass, 0 fail
  • New test (iframeFrameZoomGuard.test.tsx) renders a real CanvasRoot and asserts the frame iframe document cancels ctrl/meta-wheel, gesturestart, gesturechange, and multi-touch pinch, while leaving single-finger scroll alone.
  • Live in the running editor (against the real site): all three frames (mobile/tablet/desktop) report ctrlWheelPrevented=true and gesturestartPrevented=true inside their iframe documents (the gesturestart block is the new behavior — before the fix only wheel was cancelled, by the forwarder).

Note: the pre-push hook surfaces 3 react-doctor warnings on IframeFrameSurface.tsx (the forwardRef import, the wheel forwarder's listener, the deliberately same-origin/unsandboxed canvas iframe). All are pre-existing and unrelated to this change; they appear only because the file is in the diff. bun run lint (the CI gate) passes.

🤖 Generated with Claude Code

`AdminZoomGuard` cancels pinch / ctrl-wheel / Safari gesture browser zoom, but
it is installed only on the parent admin document. Each canvas breakpoint frame
renders in its OWN iframe document, and wheel/gesture events that originate
there never cross the boundary to the parent — so pinch-zooming over a frame
(e.g. while hovering its "Switch to … breakpoint" toolbar buttons) zoomed the
entire admin page, which is supposed to be locked.

The design frame had an ad-hoc wheel forwarder that happened to preventDefault
wheel events (to drive canvas pan), but it never handled `gesturestart` /
`gesturechange` or multi-touch pinch, and live-preview frames had no guard at
all. Install the existing `installAdminZoomGuard` inside every frame document
(design and live). The wheel forwarder still routes pan/zoom to the canvas; the
guard only cancels the browser's native zoom default.

Verified live in the editor: all three frame iframes now cancel ctrl-wheel and
gesturestart. Test renders a real CanvasRoot and asserts the frame document
cancels pinch/gesture/multi-touch zoom while leaving single-finger scroll alone.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant