I am experiencing an issue with modals in app bridge 4.x
Specifically, I am showing some components that rely on mouse events ( an interactive map) in a max’ed out modal ( closest I can get to a full screen mode ).
Example code to show the issue is below.
The code shows a demo canvas, that prints out its mouse events in the log.
This works as expected when viewed in a normal page. Specifically, all events have coordinates, and mouse wheel events are shown.
When the same component is viewed in a modal, mouse events do not have coordinates, and mouse wheel events are completely missing!
/**
* CanvasLoggerBugDemo.tsx
*
* This page demonstrates a minimal, self-contained CanvasEventLogger for bug reporting.
*
* Features:
* - Renders a 200x200 canvas that logs all mouse events to the browser console.
* - Provides a button to open the same canvas in an App Bridge modal (Shopify style).
* - Only one instance of the canvas is rendered at a time (either on the page or in the modal).
*
* Usage:
* - Interact with the canvas directly on the page and observe mouse events in the browser console.
* - Click "Show Canvas in Modal" to open the App Bridge modal and interact with the same canvas.
* - Useful for reproducing and reporting bugs related to event handling in modals vs. main page.
*
* BUG DEMO: All expected mouse events are logged when the canvas is viewed on the page, but only a subset of mouse events are logged when the canvas is shown in the modal. This demonstrates a possible event propagation or modal isolation bug.
*/
import React, { useRef, useEffect, useState } from "react";
import { Button, Page } from "@shopify/polaris";
import { Modal, useAppBridge } from "@shopify/app-bridge-react";
// Self-contained CanvasEventLogger for bug reporting
const eventNames = [
"mousemove",
"mousedown",
"mouseup",
"mouseenter",
"mouseleave",
"click",
"dblclick",
"contextmenu",
"wheel"
];
/**
* CanvasEventLogger
*
* Renders a 200x200 canvas and logs all mouse events (move, click, enter, leave, etc.)
* to the browser console. Used for event propagation and modal bug reproduction.
*/
function CanvasEventLogger() {
const canvasRef = useRef<HTMLCanvasElement>(null);
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const logEvent = (e: Event) => {
if (e instanceof MouseEvent) {
console.log(
`[${e.type}] x:${e.offsetX}, y:${e.offsetY}, button:${e.button}`
);
} else {
console.log(`[${e.type}]`);
}
};
eventNames.forEach(eventName => {
canvas.addEventListener(eventName, logEvent);
});
return () => {
eventNames.forEach(eventName => {
canvas.removeEventListener(eventName, logEvent);
});
};
}, []);
return (
<div style={{ display: "flex", flexDirection: "column", alignItems: "center" }}>
<div style={{ marginBottom: 8 }}>Interact with the canvas below (check browser console for logs):</div>
<canvas
ref={canvasRef}
width={200}
height={200}
style={{ border: "1px solid #888", background: "#fafafa" }}
/>
</div>
);
};
/**
* CanvasLoggerBugDemo
*
* Page component for bug reporting. Shows the CanvasEventLogger on the page and in a modal.
* Only one instance is ever rendered at a time. Use this to demonstrate event issues.
*/
function CanvasLoggerBugDemo() {
return (
<Page title="CanvasEventLogger Bug Demo" fullWidth>
<h2>CanvasEventLogger Demo for Bug Report</h2>
<Button onClick={() => shopify.modal.show("canvasLoggerModal")}>Show Canvas in Modal</Button>
{/* Only render the canvas on the page if modal is not open */}
<div style={{ marginTop: 24 }}>
<CanvasEventLogger />
</div>
<Modal
id="canvasLoggerModal"
variant="base"
>
<CanvasEventLogger />
</Modal>
</Page>
);
};
export default CanvasLoggerBugDemo