Skip to content

Conversation

pan-kot
Copy link
Member

@pan-kot pan-kot commented Sep 9, 2025

Description

The issue was observed when we run integ tests with React 18: #3829

With React 18 (strict mode or not) the mixed charts popover behaves differently: when the cursor moves from popover content to a bar series it was open for, the popover does not reopen: the user has to move the cursor outside the bar, and then back inside.

That happens because the popover state is controlled with a useLayoutEffect, and it depends on a series of state changes:

  1. When the cursor leaves the popover, we set the highlighted group to null (therefore the popover should be hidden).
  2. When the cursor enters the next bar, we set the highlighted group to that bar index (which is the same index that was before we hide it).
  3. Because both state changes happen in quick succession, React 18 ignores the first one for that layout effect, and because the next state is the same that was before - the callback does not fire, and the popover does not reopen.

See how the popover re-opens when the cursor is moved slowly, but does not reopen when it is moved fast:

Screen.Recording.2025-09-10.at.09.41.45.mov

How has this been tested?

  • Existing integration tests in React 16 and 18
  • Screenshot tests
Review checklist

The following items are to be evaluated by the author(s) and the reviewer(s).

Correctness

  • Changes include appropriate documentation updates.
  • Changes are backward-compatible if not indicated, see CONTRIBUTING.md.
  • Changes do not include unsupported browser features, see CONTRIBUTING.md.
  • Changes were manually tested for accessibility, see accessibility guidelines.

Security

Testing

  • Changes are covered with new/existing unit tests?
  • Changes are covered with new/existing integration tests?

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Copy link

codecov bot commented Sep 9, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.20%. Comparing base (ce7b93a) to head (78958de).
⚠️ Report is 9 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3851      +/-   ##
==========================================
+ Coverage   97.14%   97.20%   +0.05%     
==========================================
  Files         844      844              
  Lines       24515    24555      +40     
  Branches     8645     8659      +14     
==========================================
+ Hits        23815    23868      +53     
+ Misses        693      639      -54     
- Partials        7       48      +41     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@pan-kot pan-kot changed the title experiment: mixed chart tests chore: Fixes mixed charts popover behaviour for React 18 Sep 10, 2025
if (this.currentIndex) {
await this.click(this.wrapper.findDetailPopover().findDismissButton().toSelector());
// Wait for popover dismiss reopen delay.
await this.pause(50);
Copy link
Member Author

Choose a reason for hiding this comment

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

The new implementation prevents the popover to be shown immediately after dismiss using a small timeout, which needs to be considered also in tests.

// The delay prevents re-opening popover immediately upon dismissing,
// so that the popover actually closes. It can be reopened with the next
// hover or focus event that occurs after the delay.
const REOPEN_DELAY_MS = 50;
Copy link
Member Author

Choose a reason for hiding this comment

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

The popover should not be reopen immediately upon dismissal - that is an existing requirement. That was ensured by checking the highlighted series index/id: if same, the popover will not reopen. The new implementation achieves the same with a small timeout, yet now it is also possible to re-open the popover shortly after it is dismissed by hovering over the same series the popover was open for before.

scaledX: point.x,
label: point.datum?.x ?? null,
});
showPopover();
Copy link
Member Author

Choose a reason for hiding this comment

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

We now show the popover the moment a point or series is highlighted, without relying on the dependencies change.

clearAllHighlights();
dismissPopover();
}, [dismissPopover, clearAllHighlights]);
hidePopover();
Copy link
Member Author

Choose a reason for hiding this comment

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

Hiding the popover (e.g. when the cursor leaves a series) is not the same as dismissing it - we should not prevent its reopen in that case.

if (highlightedX !== null || highlightedPoint !== null) {
showPopover();
}
}, [highlightedX, highlightedPoint, showPopover]);
Copy link
Member Author

Choose a reason for hiding this comment

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

If highlightedX was 1 (showing the popover for the 1st group) and then it changes as 1 -> null -> 1 in a quick succession, that intermediate transition to null is ignored by React 18. As result, the effect callback is not fired, thus not showing the popover.

expectValues([47, 7, 8]);
});

test('opens popover for each series (line)', () => {
Copy link
Member Author

Choose a reason for hiding this comment

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

This test is needed to increase test coverage of the mixed chart container

@pan-kot pan-kot marked this pull request as ready for review September 10, 2025 08:06
@pan-kot pan-kot requested a review from a team as a code owner September 10, 2025 08:06
@pan-kot pan-kot requested review from ernst-dev and removed request for a team September 10, 2025 08:06
@pan-kot pan-kot added this pull request to the merge queue Sep 12, 2025
Merged via the queue into main with commit 2a71e86 Sep 12, 2025
38 checks passed
@pan-kot pan-kot deleted the r18-charts branch September 12, 2025 10:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants