Mouse event bug in Modals

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
1 Like

Hey @Peter_Strand :waving_hand: - thanks for sharing your Typescript file there. I tried to replicate the issue using your code on just a regular page using Polaris, and wasn’t able to, so I do think you’re right in thinking it might be related to App Bridge (or how App Bridge is set up on your end there).

Can you let me know which version of @shopify/app-bridge-react you’re using using and if you’re able to, share your full implementation of this in App Bridge if possible? As well - is this happening in all browsers or just one? Just want to narrow down if it’s specific to a particular browser or a particular setting (addons extensions_ you have in your browser).

If you’d like to get in touch via DM to share any of those details, just ping me here as well and I can take a look with you :slight_smile:

"@shopify/app-bridge-react": "^4.1.10"
"@shopify/polaris": "^13.9.0"

It happens on Chrome and Safari - tried only on various mac’s
I have the code above in an unpublished test Shopify app - I can give you the details for you to install it in a test store - would that work for you?

( can I DM from this platform? )

Hey @Peter_Strand - happy to take a look. I’ll DM you on my end here!