@@ -38,6 +38,19 @@ const HIDDEN_PREVIEW_BOUNDS = {
3838 viewportHeight : 0 ,
3939} as const ;
4040
41+ /**
42+ * Selector that matches any popup positioner element portaled to the body.
43+ * When any of these are present, the native BrowserView overlay should be
44+ * hidden so it doesn't render on top of dropdown menus / popovers.
45+ */
46+ const POPUP_POSITIONER_SELECTOR = [
47+ '[data-slot="menu-positioner"]' ,
48+ '[data-slot="popover-positioner"]' ,
49+ '[data-slot="select-positioner"]' ,
50+ '[data-slot="combobox-positioner"]' ,
51+ '[data-slot="autocomplete-positioner"]' ,
52+ ] . join ( "," ) ;
53+
4154function getActiveTab ( state : PreviewTabsState ) : PreviewTabState | null {
4255 if ( ! state . activeTabId ) return null ;
4356 return state . tabs . find ( ( t ) => t . tabId === state . activeTabId ) ?? null ;
@@ -117,11 +130,15 @@ export function PreviewPanel({ threadId, onClose }: PreviewPanelProps) {
117130 if ( ! element ) return HIDDEN_PREVIEW_BOUNDS ;
118131
119132 const rect = element . getBoundingClientRect ( ) ;
133+ // Hide the native BrowserView when any popup/dropdown is open so it
134+ // doesn't render on top of menus (native overlays ignore CSS z-index).
135+ const hasOpenPopup = document . querySelector ( POPUP_POSITIONER_SELECTOR ) !== null ;
120136 const visible =
121137 tabsState . tabs . length > 0 &&
122138 document . visibilityState === "visible" &&
123139 rect . width > 0 &&
124- rect . height > 0 ;
140+ rect . height > 0 &&
141+ ! hasOpenPopup ;
125142 return {
126143 x : rect . left ,
127144 y : rect . top ,
@@ -164,6 +181,11 @@ export function PreviewPanel({ threadId, onClose }: PreviewPanelProps) {
164181 lastBoundsKey = "" ;
165182 } ;
166183
184+ // Watch for popup positioners being added/removed from the DOM so we
185+ // can immediately hide/show the native BrowserView overlay.
186+ const popupObserver = new MutationObserver ( invalidateBounds ) ;
187+ popupObserver . observe ( document . body , { childList : true , subtree : false } ) ;
188+
167189 window . addEventListener ( "resize" , invalidateBounds ) ;
168190 window . addEventListener ( "scroll" , invalidateBounds , true ) ;
169191 document . addEventListener ( "visibilitychange" , invalidateBounds ) ;
@@ -176,6 +198,7 @@ export function PreviewPanel({ threadId, onClose }: PreviewPanelProps) {
176198 destroyed = true ;
177199 if ( frameId !== 0 ) window . cancelAnimationFrame ( frameId ) ;
178200 resizeObserver ?. disconnect ( ) ;
201+ popupObserver . disconnect ( ) ;
179202 window . removeEventListener ( "resize" , invalidateBounds ) ;
180203 window . removeEventListener ( "scroll" , invalidateBounds , true ) ;
181204 document . removeEventListener ( "visibilitychange" , invalidateBounds ) ;
0 commit comments