diff --git a/ui/src/components/browser/browser-panel.test.ts b/ui/src/components/browser/browser-panel.test.ts index e81ddd9dadb0..a3ca17876a5d 100644 --- a/ui/src/components/browser/browser-panel.test.ts +++ b/ui/src/components/browser/browser-panel.test.ts @@ -69,6 +69,22 @@ describe("normalizeBrowserUrlDraft", () => { expect(panel.browserPanelIsOpen()).toBe(true); }); + it("mounts when ResizeObserver is unavailable", async () => { + vi.stubGlobal("ResizeObserver", undefined); + const panel = document.createElement("openclaw-browser-panel") as unknown as HTMLElement & { + available: boolean; + embedded: boolean; + renderRoot: ShadowRoot; + updateComplete: Promise; + }; + panel.available = true; + panel.embedded = true; + document.body.append(panel); + await panel.updateComplete; + + expect(panel.renderRoot.querySelector(".bp")).not.toBeNull(); + }); + it("uses the shared surface empty state when the embedded browser has no tabs", async () => { const panel = document.createElement("openclaw-browser-panel") as unknown as HTMLElement & { available: boolean; diff --git a/ui/src/components/browser/browser-panel.ts b/ui/src/components/browser/browser-panel.ts index 406dca2a01d1..5ef749adc075 100644 --- a/ui/src/components/browser/browser-panel.ts +++ b/ui/src/components/browser/browser-panel.ts @@ -60,15 +60,7 @@ class OpenClawBrowserPanel extends OpenClawLitElement implements BrowserPanelCon }); private readonly onToggleRequest = (event: Event) => this.handleToggleRequest(event); private embeddedRefreshTimer: number | null = null; - private readonly viewportResizeObserver = new ResizeObserver((entries) => { - const entry = entries[0]; - if (entry) { - this.browserPanelController.handleViewportResize( - entry.contentRect.width, - entry.contentRect.height, - ); - } - }); + private viewportResizeObserver: ResizeObserver | null = null; private observedViewportElement: Element | null = null; static override styles = [ @@ -95,7 +87,8 @@ class OpenClawBrowserPanel extends OpenClawLitElement implements BrowserPanelCon this.clearEmbeddedRefresh(); super.disconnectedCallback(); window.removeEventListener(BROWSER_PANEL_TOGGLE_EVENT, this.onToggleRequest); - this.viewportResizeObserver.disconnect(); + this.viewportResizeObserver?.disconnect(); + this.viewportResizeObserver = null; this.observedViewportElement = null; } @@ -135,9 +128,18 @@ class OpenClawBrowserPanel extends OpenClawLitElement implements BrowserPanelCon const viewportElement = this.renderRoot.querySelector(".bp-viewport"); if (viewportElement !== this.observedViewportElement) { // The viewport is transient while the dock opens, closes, or becomes unavailable. - this.viewportResizeObserver.disconnect(); + this.viewportResizeObserver?.disconnect(); this.observedViewportElement = viewportElement; - if (viewportElement) { + if (viewportElement && typeof ResizeObserver === "function") { + this.viewportResizeObserver ??= new ResizeObserver((entries) => { + const entry = entries[0]; + if (entry) { + this.browserPanelController.handleViewportResize( + entry.contentRect.width, + entry.contentRect.height, + ); + } + }); this.viewportResizeObserver.observe(viewportElement); } }