@@ -267,16 +267,22 @@ export function isTextClipped(element: HTMLElement): boolean {
267267
268268/**
269269 * Whether a tooltip trigger is still visibly rendered. `checkVisibility` (where available) catches
270- * `display: none` and an inherited `visibility: hidden` anywhere up the tree; the fallback for
271- * engines without it (Safari < 17.4, jsdom) reads the element's computed `visibility`, which still
272- * inherits from hidden ancestors.
270+ * `display: none` and an inherited `visibility: hidden` anywhere up the tree. The fallback for
271+ * engines without it (Safari < 17.4, jsdom) reads the element's computed `visibility` — which
272+ * inherits from hidden ancestors — and then walks the ancestor chain for `display: none`, which
273+ * does not inherit. Computed styles, not layout (`getClientRects`/`offsetParent`), on purpose:
274+ * jsdom does no layout, so a layout-based check would misread every trigger as hidden in tests.
273275 */
274276function isVisiblyRendered ( element : HTMLElement ) : boolean {
275277 if ( ! element . isConnected ) return false
276278 if ( typeof element . checkVisibility === 'function' ) {
277279 return element . checkVisibility ( { checkVisibilityCSS : true , visibilityProperty : true } )
278280 }
279- return getComputedStyle ( element ) . visibility !== 'hidden'
281+ if ( getComputedStyle ( element ) . visibility === 'hidden' ) return false
282+ for ( let node : HTMLElement | null = element ; node ; node = node . parentElement ) {
283+ if ( getComputedStyle ( node ) . display === 'none' ) return false
284+ }
285+ return true
280286}
281287
282288/** Clamps `value` to the inclusive `[min, max]` range. */
0 commit comments