primefaces / primereact

The Most Complete React UI Component Library
https://primereact.org
MIT License
6.93k stars 1.05k forks source link

Menu, ContextMenu, TieredMenu, OverlayPanel: Click outside of menu does not close component, when rendered in a different browsing context (e.g. window.open) #7441

Open codalf opened 1 day ago

codalf commented 1 day ago

Describe the bug

When a menu is rendered in a newly created window (using window.open()), the menu does not close when clicking outside of the menu (which is the normal behavior when rendered in the main window). This seems to be due to the usage of useEventListener and useOverlayListener without specifying target, which then defaults to document/'window'. However in this case, it should be the ownerDocument of the menu or the respective window.

Reproducer

StackBlitz does not support window.open() properly

System Information

System:
    OS: Windows 11 10.0.22631
    CPU: (16) x64 AMD Ryzen 7 PRO 5850U with Radeon Graphics
    Memory: 12.47 GB / 30.83 GB
  Binaries:
    Node: 20.11.1 - C:\Program Files\nodejs\node.EXE
    npm: 10.2.4 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Chrome: master_preferences
    Edge: Chromium (127.0.2651.98)
    Internet Explorer: 11.0.22621.3527
  npmPackages:
    primereact: ^10.6.0 => 10.8.4
    react: ^18.3.0 => 18.3.1

Steps to reproduce the behavior

StackBlitz unfortuantely always returns null when calling window.open(), but here is the code:

export default function PopupDoc() {
    const menuLeft = useRef(null);
    const items = [
        {
            label: 'Options',
            items: [
                {
                    label: 'Refresh',
                    icon: 'pi pi-refresh'
                },
                {
                    label: 'Export',
                    icon: 'pi pi-upload'
                }
            ]
        }
    ];

    const handleOpenPopup = () => {
        const popupWindow = window.open('', 'Popup', 'width=600,height=400');
        console.log(popupWindow);
        if (popupWindow) {
            popupWindow.document.head.insertAdjacentHTML(
                'beforeend',
                '<link rel="stylesheet" href="<path to primereact stylesheet>" />'
            );
            popupWindow.document.body.insertAdjacentHTML(
                'afterbegin',
                '<div id="popup-root"></div>'
            );

            console.log("Mounted root");

            // Render the Popup component using ReactDOM in the new window
            ReactDOM.createRoot(popupWindow.document.getElementById('popup-root')).render(
                <React.StrictMode>
                    <PrimeReactProvider appendTo={popupWindow.document.body}>
                    <div className="card flex justify-content-center">
                            <Menu model={items} popup ref={menuLeft} id="popup_menu_left" />
                            <Button label="Show Left" icon="pi pi-align-left" className="mr-2" onClick={(event) => menuLeft.current.toggle(event)} aria-controls="popup_menu_left" aria-haspopup />
                        </div>
                    </PrimeReactProvider>
                </React.StrictMode>
            );
        }
    };

    return (
        <div className="card flex justify-content-center">
            <Button onClick={handleOpenPopup}>Open Popup With Menu</Button>
       </div>
    )
}

Expected behavior

In popup windows, menu should just behave as in the normal browser window, i.e. close when clicking outside of the window