question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[1.4.1] Tooltips with new Identity and openDelay dont hide after first hover

See original GitHub issue

🐛 Bug report

Tooltips with openDelay that get a new identity will open and not close after the first time the mouse hovers over the trigger, if the mouse leaves before the tooltip opens

💥 Steps to reproduce

  1. Have a tooltip with openDelay > 0
  2. Have it re-mount with a new identity
  3. Hover over the tooltip-trigger
  4. Leave the trigger before the tooltip opens
  5. See that after the configured delay, the tooltip opens and stays open

💻 Link to reproduction

CodeSandbox reproduction: https://codesandbox.io/s/hardcore-water-jvxlj?file=/src/App.js:387-390

🧐 Expected behavior

The tooltip should neither open, nor stay open if i leave the trigger before it opens

🧭 Possible Solution

Some debugging showed, that the mouseleave-event isn’t triggered in this case. Maybe the ref/domnode provided here has the wrong value? https://github.com/chakra-ui/chakra-ui/blob/1d85e472918346f1eb4ba7aed5291b9e7254e1f8/packages/tooltip/src/use-tooltip.ts#L155

🌍 System information

Software Version(s)
Chakra UI 1.4.1
Browser Chrome 89 & Firefox 86
Operating System macOS 11.2.3

📝 Additional information

This did not happen on chakra 1.3.x

Here is a video of the error happening in the provided code-sandbox:

https://user-images.githubusercontent.com/20770029/112314138-f6ec2e80-8ca8-11eb-8af0-c0f4d024e142.mp4

Update

Using the automatically created Build from #4442 Fixes the Issue in the initial Codesandbox: https://codesandbox.io/s/affectionate-mccarthy-bpmjf?file=/src/index.js

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:4
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

4reactions
deluccacommented, Jun 10, 2021

Still happening 😕

2reactions
5ebastianMeiercommented, Jul 21, 2021

I was able to replicate the bug and can confirm that the assumed cause of the error is just that.

Naive fix to confirm the suggestion

To fix the bug I simply had to replace this line in useTooltip()

useEventListener("mouseleave", closeWithDelay, ref.current);

with this

React.useEffect(() => {
  if (!ref.current) {
    return;
  }
  ref.current.addEventListener('mouseleave', closeWithDelay);
  return () => {
    ref.current?.removeEventListener('mouseleave', closeWithDelay)
  }
}, [])

Explanation

When useEventListener is first called, the ref object does not have a value yet, therefore the event listener is not being attached. On any render after the initial render useEventListener is being called again with a non-null value and will register the event listener as intended.

This is what the implementation of useEventListener looks like:

export function useEventListener<K extends keyof DocumentEventMap>(
  event: K | (string & {}),
  handler: (event: DocumentEventMap[K]) => void,
  env?: EventListenerEnv,
  options?: boolean | AddEventListenerOptions,
) {
  const listener = useCallbackRef(handler) as EventListener

  React.useEffect(() => {
    const node = runIfFn(env) ?? document

    node.addEventListener(event, listener, options)
    return () => {
      node.removeEventListener(event, listener, options)
    }
  }, [event, env, options, listener])

  return () => {
    const node = runIfFn(env) ?? document
    node.removeEventListener(event, listener, options)
  }
}

Suggested fixes

Wrap the ref element in a callback function

Considering that useEventListener also allows the env object to be a function, we can wrap the instance retrieval into a callback like so:

const getInstance = React.useCallback(() => {
  return ref.current;
}, []);
useEventListener("mouseleave", closeWithDelay, getInstance);

When I applied this change in useTooltip I was not able to reproduce this issue anymore.

Add ref unwrapping to useEventListener

I’m not entirely sure what the reason for this hook was to not accept a ref object as env. If useEventListener would check for the env object to be a ref and unwrap it internally, it would possibly result in a more flexible API.

I don’t have a proposal at hand, but wanted to mention the thought anyway for further discussion.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Bootstrap tooltip, invert its function: display all and hide on hover
I have a page with many tooltips and I want to display all at first. They all have a "tooltipWarn" class. <span class='warning...
Read more >
Tooltips - Bootstrap
Documentation and examples for adding custom Bootstrap tooltips with CSS and JavaScript using CSS3 ... Triggering tooltips on hidden elements will not work....
Read more >
Tooltip - Mantine
hover – mouse hover event, true by default; focus – focus/blur events excluding clicks on the target element, false by default; touch –...
Read more >
Tooltips in the time of WCAG 2.1 | Sarah Higley
It is hidden by default, and becomes available on hover or focus of the control it describes. That definition could even be narrowed...
Read more >
Tooltip - Adobe Spectrum
All tooltips have a label. The label communicates the contextual help or information about specific components when a user hovers over or focuses...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found