-
-
Notifications
You must be signed in to change notification settings - Fork 983
Description
User Story
As a web developer, I can render a MapLibre map into a popup window while keeping the JavaScript context in the main window, so that I can build "pop-out" features with shared application state.
Rationale
Why is this feature needed?
Modern web applications implement "pop-out" features that allow users to open content in separate windows while maintaining shared state. This is achieved using window.open('about:blank') combined with ReactDOM.createPortal() or direct DOM manipulation, where JS runs in the main window but UI renders into the popup's DOM.
Currently, MapLibre fails in this scenario because it uses window-scoped globals (window, document, instanceof HTMLElement, instanceof MouseEvent) that don't work across window contexts.
Example use cases
- Multi-window web applications: Trading platforms, analytics dashboards, or collaboration tools where users can pop out widgets to secondary monitors
- Electron/Tauri/WebView-based desktop apps: Desktop applications built with web technologies often need to support multiple windows sharing the same JS context
- Picture-in-picture style features: Detachable map panels that float independently while staying connected to the main application
- Kiosk and digital signage: Multi-display setups where a single application drives content across multiple screens/windows
Can it be done today? Is there a workaround?
No viable workaround exists.
The only alternative is to load MapLibre separately in the popup window, but this:
- Breaks shared state with the main application
- Requires duplicating the library and styles
- Prevents React portal patterns that many apps rely on
- Adds complexity for cross-window communication (postMessage, etc.)
Impact
What if we do nothing?
Developers building multi-window web applications cannot use MapLibre for pop-out features. They must either:
- Abandon the pop-out pattern for map-containing components
- Use a different map library that supports cross-window rendering
- Maintain a custom fork of MapLibre with cross-window fixes
This limits MapLibre's adoption in enterprise web applications and Electron/WebView-based desktop apps where multi-window support is a common requirement.
Minimal Reproduction
Save as HTML and open in browser. Click the button to open a map in a popup window.
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/[email protected]/dist/maplibre-gl.js"></script>
</head>
<body>
<button onclick="openMapInPopup()">Open Map in Popup Window</button>
<script>
function openMapInPopup() {
const popup = window.open('about:blank', '_blank', 'width=800,height=600');
popup.document.write(`
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/maplibre-gl.css">
<div id="map" style="width:100%;height:100%"></div>
`);
popup.document.close();
// Container is in popup, but MapLibre JS runs in main window
new maplibregl.Map({
container: popup.document.getElementById('map'),
style: 'https://demotiles.maplibre.org/style.json',
});
}
</script>
</body>
</html>Symptoms:
- Map fails to render. Console shows:
Uncaught Error: Invalid type: 'container' must be a String or HTMLElement. - Even after bypassing the container validation, the map renders but does not respond to any mouse or keyboard events.
Proposed Implementation
Derive ownerDocument and ownerWindow from the container element instead of using globals:
- Use
container.ownerDocumentandownerDocument.defaultViewinstead of globaldocument/window - Bind document/window-level events to the container's ownerDocument/ownerWindow
- Use duck typing for event detection instead of
instanceof - Pass
ownerWindowtorequestAnimationFrame()andResizeObserver
I have a working implementation and would be happy to submit a PR.