-
-
Notifications
You must be signed in to change notification settings - Fork 11
Hide preview overlay while popups are open #110
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -38,6 +38,19 @@ const HIDDEN_PREVIEW_BOUNDS = { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| viewportHeight: 0, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } as const; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Selector that matches any popup positioner element portaled to the body. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * When any of these are present, the native BrowserView overlay should be | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * hidden so it doesn't render on top of dropdown menus / popovers. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const POPUP_POSITIONER_SELECTOR = [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| '[data-slot="menu-positioner"]', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| '[data-slot="popover-positioner"]', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| '[data-slot="select-positioner"]', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| '[data-slot="combobox-positioner"]', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| '[data-slot="autocomplete-positioner"]', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ].join(","); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function getActiveTab(state: PreviewTabsState): PreviewTabState | null { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!state.activeTabId) return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return state.tabs.find((t) => t.tabId === state.activeTabId) ?? null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -117,11 +130,15 @@ export function PreviewPanel({ threadId, onClose }: PreviewPanelProps) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!element) return HIDDEN_PREVIEW_BOUNDS; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const rect = element.getBoundingClientRect(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Hide the native BrowserView when any popup/dropdown is open so it | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // doesn't render on top of menus (native overlays ignore CSS z-index). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const hasOpenPopup = document.querySelector(POPUP_POSITIONER_SELECTOR) !== null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const visible = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tabsState.tabs.length > 0 && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| document.visibilityState === "visible" && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rect.width > 0 && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rect.height > 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rect.height > 0 && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| !hasOpenPopup; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+133
to
+141
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| x: rect.left, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| y: rect.top, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -164,6 +181,11 @@ export function PreviewPanel({ threadId, onClose }: PreviewPanelProps) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| lastBoundsKey = ""; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Watch for popup positioners being added/removed from the DOM so we | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // can immediately hide/show the native BrowserView overlay. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const popupObserver = new MutationObserver(invalidateBounds); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const popupObserver = new MutationObserver(invalidateBounds); | |
| const popupObserver = new MutationObserver((mutations) => { | |
| for (const mutation of mutations) { | |
| if (mutation.type !== "childList") continue; | |
| for (const node of Array.from(mutation.addedNodes)) { | |
| if (node instanceof Element) { | |
| if ( | |
| (typeof (node as Element).matches === "function" && | |
| (node as Element).matches(POPUP_POSITIONER_SELECTOR)) || | |
| (typeof (node as Element).querySelector === "function" && | |
| (node as Element).querySelector(POPUP_POSITIONER_SELECTOR)) | |
| ) { | |
| invalidateBounds(); | |
| return; | |
| } | |
| } | |
| } | |
| for (const node of Array.from(mutation.removedNodes)) { | |
| if (node instanceof Element) { | |
| if ( | |
| (typeof (node as Element).matches === "function" && | |
| (node as Element).matches(POPUP_POSITIONER_SELECTOR)) || | |
| (typeof (node as Element).querySelector === "function" && | |
| (node as Element).querySelector(POPUP_POSITIONER_SELECTOR)) | |
| ) { | |
| invalidateBounds(); | |
| return; | |
| } | |
| } | |
| } | |
| } | |
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
computeBoundsruns on every animation frame (the RAF loop insyncBounds). Addingdocument.querySelector(POPUP_POSITIONER_SELECTOR)here means we traverse the DOM ~60 times/sec while the preview bridge is active, even when the preview isn't eligible to be shown. Consider avoiding the per-frame query by (a) short-circuiting on the cheap checks first (tabs length, document visibility, rect size) and only querying when those pass, and/or (b) cachinghasOpenPopupin a ref that’s updated by theMutationObserver/ popup lifecycle socomputeBoundsis O(1).