tippyjs icon indicating copy to clipboard operation
tippyjs copied to clipboard

Calling hide breaks focus restoration when window is blurred

Open zhouzi opened this issue 3 years ago • 5 comments

Bug description

Tippy manually blurs the active element when the window is blurred, if a tooltip is attached to it and if the tooltip is hidden:

https://github.com/atomiks/tippyjs/blob/ad85f6feb79cf6c5853c43bf1b2a50c4fa98e7a1/src/bindGlobalEventListeners.ts#L42-L58

This is breaking the browser's focus restoration when switching back to the window.

Reproduction

StackBlitz link: https://stackblitz.com/edit/web-platform-briuf1?file=index.html

  1. Click in the input with a tooltip, the tooltip is shown
  2. Press alt+tab to switch to another window
  3. Press alt+tab again to switch back to the window with the input

The input should be focused but it's not the case. The reproduction includes an input without a tooltip so you can compare the behaviour.

It seems that this was initially implemented as a fix to #72. It would argue that it goes against the browser's behaviour and what's reported in #72 is not an issue but what is expected. But there might be other valid reasons I am not aware of.

Let me know what you think and I'd be happy to submit a PR.

zhouzi avatar Jun 28 '22 16:06 zhouzi

A solution that wouldn't run the risk of breaking current users' expectations would be to add an option that defaults to the current behaviour. With a way to turn it off.

zhouzi avatar Jun 28 '22 16:06 zhouzi

I agree it's expected in this case, what it was trying to fix was the case where the ref has focus but the tippy is hidden (due to the hideOnClick: true behavior), coming back to the window would show it unexpectedly. Probably instead it should be checking to see if it's visible at the time the window is blurred.

EDIT: okay, it checks isVisible but the ref gets blurred when the window is blurred so that's why the check is failing I guess? I wonder if this behavior has changed in browsers somewhat recently? Checking isMounted instead would work, provided it has an animation/transition. If not it would also fail in this case.

atomiks avatar Jun 29 '22 07:06 atomiks

okay, it checks isVisible but the ref gets blurred when the window is blurred so that's why the check is failing I guess?

What do you mean by the check is failing? The input receives a blur event, isVisible is false so it blurs the focused element. Seems fine.

When switching window, the input receives a blur event but it's still the activeElement. We could leverage that to set a ignoreNextFocusEvent to true. Alternatively we could store a reference of the new activeElement on blur and then compare it with the reference on focus. If it's the same then ignore the focus event. But that's more work and data to store in memory.

zhouzi avatar Jun 29 '22 09:06 zhouzi

What do you mean by the check is failing? The input receives a blur event, isVisible is false so it blurs the focused element. Seems fine.

If the tippy was visible at the time the window blurred and the input lost focus, it shouldn't close. But the check fails here because the trigger blur event is firing right before the window blur event (I think), so it thinks it's not visible at the time the window blurred even though it was.

But yeah open to a PR with a better solution 👍

atomiks avatar Jun 29 '22 09:06 atomiks

I wanted to help with this and submit a PR but I can't install tippy locally. I have a MacBook with an Apple M1 processor and ran into these issues:

  • When running yarn test: failed to build docker-chromium, probably https://github.com/gidztech/jest-puppeteer-docker/issues/47
  • When running yarn dev: too many open files, probably https://github.com/facebook/watchman/issues/923

zhouzi avatar Jul 09 '22 14:07 zhouzi