From b1e960e6a95a7a52df3c48c9d4d36ba7e7a886df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Wallstr=C3=B6m?= <21986391+FredrikWallstrom@users.noreply.github.com> Date: Wed, 16 Sep 2026 08:18:29 +0200 Subject: [PATCH] fix(picker): stop the dropdown resizing itself inside its own resize observer With `inheritParentWidth` the restyle writes the anchor's width onto the container the observer watches, so the first callback resizes it mid-delivery and the browser reports a ResizeObserver loop. Restyle on the next frame instead. Co-Authored-By: Claude Opus 5 (1M context) --- src/components/portal/portal.tsx | 35 ++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/components/portal/portal.tsx b/src/components/portal/portal.tsx index 9d4544b6aa..29d80fc390 100644 --- a/src/components/portal/portal.tsx +++ b/src/components/portal/portal.tsx @@ -118,6 +118,7 @@ export class Portal { private loaded = false; private observer: ResizeObserver; private writtenStyles: Partial> = {}; + private scheduledRestyle: number = null; constructor() { this.parents = new WeakMap(); @@ -333,6 +334,7 @@ export class Portal { private destroyPopper() { this.observer?.disconnect(); + this.cancelScheduledRestyle(); this.popperInstance?.destroy(); this.popperInstance = null; } @@ -343,16 +345,41 @@ export class Portal { } this.observer ??= new ResizeObserver(() => { - if (this.popperInstance) { - this.styleContainer(); - this.popperInstance.update(); - } + this.scheduleRestyle(); }); this.observer.observe(this.container); this.observer.observe(this.anchorElement); } + // Restyling can resize the container this observer watches, so writing from + // inside the callback re-enters it as a `ResizeObserver loop`. + private scheduleRestyle() { + if (this.scheduledRestyle !== null) { + return; + } + + this.scheduledRestyle = requestAnimationFrame(() => { + this.scheduledRestyle = null; + + if (!this.popperInstance) { + return; + } + + this.styleContainer(); + this.popperInstance.update(); + }); + } + + private cancelScheduledRestyle() { + if (this.scheduledRestyle === null) { + return; + } + + cancelAnimationFrame(this.scheduledRestyle); + this.scheduledRestyle = null; + } + private createPopperConfig(): Partial< OptionsGeneric> > {