Skip to content
This repository was archived by the owner on Sep 30, 2025. It is now read-only.

Commit deb41ab

Browse files
author
Jerad Gallinger
committed
Fix tooltip scrolling bug
1 parent 4620b2f commit deb41ab

File tree

1 file changed

+47
-15
lines changed

1 file changed

+47
-15
lines changed

polaris-react/src/components/PositionedOverlay/PositionedOverlay.tsx

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export class PositionedOverlay extends PureComponent<
8383
};
8484

8585
private overlay: HTMLElement | null = null;
86-
private scrollableContainer: HTMLElement | Document | null = null;
86+
private scrollableContainers: (HTMLElement | Document)[] = [];
8787
private observer: MutationObserver;
8888

8989
constructor(props: PositionedOverlayProps) {
@@ -93,23 +93,20 @@ export class PositionedOverlay extends PureComponent<
9393
}
9494

9595
componentDidMount() {
96-
this.scrollableContainer = Scrollable.forNode(this.props.activator);
97-
if (this.scrollableContainer && !this.props.fixed) {
98-
this.scrollableContainer.addEventListener(
99-
'scroll',
100-
this.handleMeasurement,
101-
);
96+
this.setScrollableContainers();
97+
98+
if (this.scrollableContainers.length && !this.props.fixed) {
99+
this.registerScrollHandlers();
102100
}
101+
103102
this.handleMeasurement();
104103
}
105104

106105
componentWillUnmount() {
107106
this.observer.disconnect();
108-
if (this.scrollableContainer && !this.props.fixed) {
109-
this.scrollableContainer.removeEventListener(
110-
'scroll',
111-
this.handleMeasurement,
112-
);
107+
108+
if (this.scrollableContainers.length && !this.props.fixed) {
109+
this.unregisterScrollHandlers();
113110
}
114111
}
115112

@@ -160,6 +157,10 @@ export class PositionedOverlay extends PureComponent<
160157
);
161158
}
162159

160+
get firstScrollableContainer(): HTMLElement | Document | null {
161+
return this.scrollableContainers[0] ?? null;
162+
}
163+
163164
forceUpdatePosition() {
164165
// Wait a single animation frame before re-measuring.
165166
// Consumer's may also need to setup their own timers for
@@ -186,6 +187,37 @@ export class PositionedOverlay extends PureComponent<
186187
this.overlay = node;
187188
};
188189

190+
private setScrollableContainers = () => {
191+
const containers: (HTMLElement | Document)[] = [];
192+
let scrollableContainer = Scrollable.forNode(this.props.activator);
193+
194+
if (scrollableContainer) {
195+
containers.push(scrollableContainer);
196+
197+
while (scrollableContainer?.parentElement) {
198+
scrollableContainer = Scrollable.forNode(
199+
scrollableContainer.parentElement,
200+
);
201+
202+
containers.push(scrollableContainer);
203+
}
204+
}
205+
206+
this.scrollableContainers = containers;
207+
};
208+
209+
private registerScrollHandlers = () => {
210+
this.scrollableContainers.forEach((node) => {
211+
node.addEventListener('scroll', this.handleMeasurement);
212+
});
213+
};
214+
215+
private unregisterScrollHandlers = () => {
216+
this.scrollableContainers.forEach((node) => {
217+
node.removeEventListener('scroll', this.handleMeasurement);
218+
});
219+
};
220+
189221
private handleMeasurement = () => {
190222
const {lockPosition, top} = this.state;
191223

@@ -201,7 +233,7 @@ export class PositionedOverlay extends PureComponent<
201233
measuring: true,
202234
}),
203235
() => {
204-
if (this.overlay == null || this.scrollableContainer == null) {
236+
if (this.overlay == null || this.firstScrollableContainer == null) {
205237
return;
206238
}
207239

@@ -222,9 +254,9 @@ export class PositionedOverlay extends PureComponent<
222254
const activatorRect = getRectForNode(preferredActivator);
223255

224256
const currentOverlayRect = getRectForNode(this.overlay);
225-
const scrollableElement = isDocument(this.scrollableContainer)
257+
const scrollableElement = isDocument(this.firstScrollableContainer)
226258
? document.body
227-
: this.scrollableContainer;
259+
: this.firstScrollableContainer;
228260
const scrollableContainerRect = getRectForNode(scrollableElement);
229261

230262
const overlayRect = fullWidth

0 commit comments

Comments
 (0)