react-tooltip: [BUG] Tooltip position and show status not synchronized.

Describe the bug When moving from one anchor to another, sometimes the tooltip’s position is updated before its visibility. This results in some glitchy / flickering behavior.

Version of Package v5.10.6

To Reproduce

  1. Set Tooltip delayShow to 300
  2. Set Tooltip delayHide to 0
  3. Move from one anchor to another (with no space between)
  4. Observe that the tooltip first changes position and content, then hides. Then after 300ms shows again.

Expected behavior The tooltip should hide first, then update position and content.

Screenshots https://user-images.githubusercontent.com/431251/230918927-995f1ccf-2449-40d8-8a4b-948c48605393.mp4

Desktop (please complete the following information if possible or delete this section):

  • OS: MacOS
  • Browser firefox
  • Version [e.g. 22]
  • Frameworks create-react-app

Additional context Repro: https://github.com/knubie/react-tooltip-demo Somewhat, but not really related: https://github.com/ReactTooltip/react-tooltip/issues/1008

About this issue

  • Original URL
  • State: open
  • Created a year ago
  • Reactions: 2
  • Comments: 29 (12 by maintainers)

Most upvoted comments

This one will be a lot trickier to solve. The root of this problem is that the tooltip content and the tooltip position are updated independently. Since the position calculation may take more than 1 render cycle to finish, and updating the content will pretty much always take exactly 1 cycle, sometimes you’ll see the text updating before the position.

We’ve tried to fix this by updating the content and the position on the same cycle 100% of the time, but it turned out to be not that easy.

The tooltip closing when you move from one element to another is actually a bug, since the expected behavior when using delayShow is that the tooltip will stay open for as long as you’re hovering an anchor element, not close and reopen after the delay.

Here are some alternatives until we can tackle this on (it might take several days until we have the time):

  1. When using delayShow, also use delayHide with a small value (50 should be fine). This will mitigate the flickering, though sometimes you’ll still see the text updating before the tooltip has moved.
  2. Use one tooltip for each anchor element. This is really not ideal, and we usually recommend against this, but it could work on your case if you don’t have many elements (anything up to 20 tooltips on the page should be fine, maybe even more).

If you have any other ideas, please let us know.

@danielbarion we could try, but I’m guessing it won’t work.

my bet is on some weird CSS specification that safari doesn’t follow exactly as it should. maybe something to so with how opacity transition is behaving

Thanks for taking the time.

Another interesting thing to notice is how the opacity does not seem to transition properly (fade in on open) sometimes. I believe this is directly related. We’ll investigate further.

:root {
  --rt-opacity: 1;
}

Just as a heads up, I believe a recent update in the way we inject the tooltip styling into the app broke setting the opacity like this. We’ll be looking into this soon.


Closing #1051 should help with this.

@dbidwell94 please try the following setup:

<ReactTooltip
  id="tooltip"
  delayShow={1000}
  positionStrategy="fixed"
  style={{ zIndex: 1000 }}
/>

Setting opacity: 1 on the tooltip styling breaks funcionality. The correct way to set the opacity is by overriding the CSS variable like this:

:root {
  --rt-opacity: 1;
}

(As a side-note, we should probably add a more straight-forward way of setting the opacity, such as an opacity prop.)

I’ve also set positionStrategy="fixed" since the scrollbar was showing for a frame when the tooltip is inserted into the DOM. Please see if this works for you.


@knubie Please confirm if you’re setting opacity: 1 manually.

The tooltip closing when you move from one element to another is actually a bug, since the expected behavior when using delayShow is that the tooltip will stay open for as long as you’re hovering an anchor element, not close and reopen after the delay.

Ah okay. I was going to ask about this earlier. Solving that bug might be a good next step.

  1. When using delayShow, also use delayHide with a small value (50 should be fine). This will mitigate the flickering, though sometimes you’ll still see the text updating before the tooltip has moved.

This worked for me. However I noticed another issue that is kind of the opposite of the previous one: When hovering over an anchor, the tooltip’s show state is updated to true first, then a frame or two later the position and content are updated. This has the effect of the tooltip showing up at it’s previous position for a frame or two before moving to the correct position. However I was only able to replicate this in my own application and not the create-react-app demo.

To resolve that I simply added the transition CSS property back in so that the tooltip is opacity: 0 for the first frame or two.

Ideally all of the state change (show/position/content) should update synchronously. I don’t have any concrete suggestions for you at the moment, though, as I’m not that familiar with the code base.