Skip to content

fix(tooltip): prevent delayed tooltip after target moves - #17474

Open
viktorkombov wants to merge 8 commits into
masterfrom
vkombov/fix-17465
Open

fix(tooltip): prevent delayed tooltip after target moves#17474
viktorkombov wants to merge 8 commits into
masterfrom
vkombov/fix-17465

Conversation

@viktorkombov

@viktorkombov viktorkombov commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Closes #17465

Description

Fixes delayed tooltips opening after grid virtualization moves their target away from the pointer without emitting pointerleave.

Implementation

For delayed hover interactions, the tooltip captures the initial pointer coordinates and uses elementFromPoint() to verify that the target is still under the pointer before opening.

Zero-delay tooltips, non-hover triggers, and programmatic opening keep their previous behavior.

Tests

Added regression coverage verifying that:

  • A delayed tooltip remains closed when its target moves away.
  • A delayed tooltip opens when its target remains under the pointer.
  • Zero-delay hover interactions are not hit-tested.

Tooltip test suite: 67/67 passing.

Components Affected

Tooltip, including tooltip targets rendered inside virtualized Grid, Tree Grid,
and Hierarchical Grid cells.

Type of Change (check all that apply):

  • Bug fix
  • New functionality
  • Breaking change
  • Refactoring
  • Documentation
  • Demos
  • CI/CD
  • Tests
  • Changelog
  • Skills/Agents

Component(s) / Area(s) Affected:

Tooltip; virtualized grid tooltip targets.

How Has This Been Tested?

  • Unit tests
  • Manual testing
  • Automated e2e tests

Test Configuration:

  • Angular version: Repository default
  • Browser(s): Chrome / Chrome Headless
  • OS: Windows

Screenshots / Recordings

N/A

Checklist:

  • All relevant tags have been applied to this PR
  • This PR includes unit tests covering the changed behavior
  • This PR includes API docs for newly added methods/properties
  • This PR includes feature/README.MD updates
  • This PR includes general feature table updates
  • This PR includes CHANGELOG.MD updates
  • This PR contains breaking changes
  • This PR includes ng update migrations
  • This PR includes behavioral changes requiring a specification update
  • Accessibility has been verified

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a tooltip timing edge case where a delayed hover tooltip could still open after its target moved (e.g., during grid virtualization/scroll) without a corresponding pointerleave, leading to stale/mispositioned or multiple visible tooltips.

Changes:

  • Track the last known pointer coordinates for delayed hover-triggered shows and revalidate via elementFromPoint() right before opening.
  • Add Shadow DOM-aware hit testing by using the element’s root (getRootNode()) when available, with a safe fallback.
  • Add regression unit tests covering target movement during delay, no hit-testing for zero-delay, and using the latest pointer position.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
projects/igniteui-angular/directives/src/directives/tooltip/tooltip-target.directive.ts Adds delayed-hover pointer position tracking + hit-test validation (incl. Shadow DOM root support) before opening the tooltip.
projects/igniteui-angular/directives/src/directives/tooltip/tooltip.directive.spec.ts Adds regression coverage for delayed-hover validation and updates the hover helper to allow pointer coordinates.

@viktorkombov viktorkombov added the ❌ status: awaiting-test PRs awaiting manual verification label Aug 10, 2026

@mddragnev mddragnev left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, isn't that too much? Can't we just check wether the element itself has :hover over it? I mean in the _showTooltip timeout where the tooltip really opens.

@viktorkombov

Copy link
Copy Markdown
Contributor Author

Wait, isn't that too much? Can't we just check wether the element itself has :hover over it? I mean in the _showTooltip timeout where the tooltip really opens.

@mddragnev, pointerleave already cancels the pending show. Since no pointerleave was fired when virtualization moved the cell, we cannot rely on :hover to reflect the element currently under the pointer.

That’s why we need to run our own check when the delay expires using elementFromPoint(). It’s also testable in Karma, unlike :hover. I can simplify the tracking and attach pointermove only while a delayed show is pending.

@mddragnev

Copy link
Copy Markdown
Member

I disagree. However, I am only verifiying if this is working so i`ll let the reviewers look at it

@mddragnev mddragnev added ✅ status: verified Applies to PRs that have passed manual verification and removed ❌ status: awaiting-test PRs awaiting manual verification labels Aug 11, 2026
@viktorkombov

Copy link
Copy Markdown
Contributor Author

I disagree. However, I am only verifiying if this is working so i`ll let the reviewers look at it

Thanks for raising this. I simplified the implementation further and removed the pointermove tracking completely.

I also checked :hover in Chrome and Firefox. I hovered a cell using real pointer input, scrolled the virtualized grid without moving the pointer, and compared matches(':hover'), pointerleave, and elementFromPoint():

  • Chrome: hover=true, pointerleave=0, elementFromPoint() returned a different cell.
  • Firefox: the same stale state occurred intermittently during repeated wheel scrolling.

So :hover alone does not reliably identify the element currently under the pointer in this case.

The current implementation only captures the initial pointer coordinates and checks elementFromPoint() when the delay expires. Positive and negative regression tests are included.

@viktorkombov viktorkombov added ❌ status: awaiting-test PRs awaiting manual verification and removed ✅ status: verified Applies to PRs that have passed manual verification labels Aug 11, 2026
@viktorkombov

Copy link
Copy Markdown
Contributor Author

@mddragnev, You were right. I rechecked the behavior and my earlier conclusion about :hover was incorrect. The browser updates the element’s hover state even when virtualization moves it without firing pointerleave.

I reverted the coordinate and elementFromPoint() logic. The delayed callback now checks this.nativeElement.matches(':hover') before opening the tooltip. The check applies only to hover-based triggers, so focus, click, and programmatic opening remain unaffected.

I also updated the regression test to simulate the hover state explicitly, since dispatching synthetic pointer events in Karma does not update the :hover pseudo-class.

Thanks for pushing back, and apologies for the incorrect initial response.

@mddragnev mddragnev added ✅ status: verified Applies to PRs that have passed manual verification and removed ❌ status: awaiting-test PRs awaiting manual verification labels Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

grid tooltip version: 22.1.x virtualization ✅ status: verified Applies to PRs that have passed manual verification

Projects

None yet

Development

Successfully merging this pull request may close these issues.

igxTooltip in igxCell shows multiple instances and becomes "mispositioned" during grid scroll

3 participants