Tippyjs: Multiple HTML instances vs one

Created on 19 Sep 2018  路  10Comments  路  Source: atomiks/tippyjs

Hi there,

First off thanks for a lovely tooltip library! The docs are extensive, the tooltip itself is more-than-plenty
configurable and it's been a breeze to use so far!

Not sure if this is a bug report or simply me misusing tippy, but I'm trying to add an interactive options menu to every item on a list with Vue. Since an html template via direct ref is only usable once, I've set up my loop so that every list item's options menu also renders its own tooltip contents.
Then, in the component's mounted hook, I'm looping through the generated menus and initialising tippy on each:

mounted () {
  const tooltips = document.querySelectorAll('.filter-tippy')

  ;[].forEach.call(tooltips, tooltip => {
    if (tooltip._tippy) return
    tippy(tooltip, {
      html: tooltip.querySelector('[data-template]'),
      appendTo: tooltip.parentNode,
      animateFill: false,
      performance: true,
      placement: 'bottom'
    })
  })
}

Current behaviour:
screen shot 2018-09-19 at 10 48 40

I also found https://github.com/atomiks/tippyjs/issues/10 and the mention of multiple, but that doesn't seem to work for me so i'm wondering if it's the case of creating multiple instances of tippy?

When I tried to replicate this behaviour in your Codepen template, then it works as expected (an active tippy is closed before opening a new one). The bug shouldn't be anything vue-specific since I'm initiating tippy with vanilla JS. Any other information I could provide to further debug this?

Replication: https://codepen.io/ajv/pen/OoaWLB

How should I approach this situation? I thought of also having a single instance, but then I couldn't pass the item's data object to the listener and would have to read certain attributes from the event
target's data attributes, I presume.

Most helpful comment

Okay I think I found the issue:

You're using @click.stop which stops the click event from propagating up the DOM tree to the document. The document has a global click listener which handles hiding all tooltips on the document that are visible. So, either you can use the hack posted above, or remove @click.stop and replace it with something else.

All 10 comments

Do you see any errors in the console?

No, sorry. No errors and everything works for every tippy (when considering it in isolation) as they should.

Hm, don't really know, sorry :(
Maybe something is happening to the parent node container / Vue is fiddling with the DOM somehow

Can you replicate it using Vue on CodePen?

Sure thing! I hope CodeSandbox works just as well.

https://codesandbox.io/s/x278j5912o

Turns out Vue might have a hand in this, since I was now able to replicate the bug 馃

While this gets debugged there is a hack to fix this:

onShow() {
  [...document.querySelectorAll('.tippy-popper')].forEach(popper => {
    popper._tippy.hide()
  })
}

Basically select any showing poppers on the document and hide them before the new one gets shown.

Okay I think I found the issue:

You're using @click.stop which stops the click event from propagating up the DOM tree to the document. The document has a global click listener which handles hiding all tooltips on the document that are visible. So, either you can use the hack posted above, or remove @click.stop and replace it with something else.

Ah! Quite stupid of me. That's indeed the case. Thank you so much for finding that for me.
I've removed the stopPropagation calls and simply added a .contains(event.target) check into the
parent's (<li>) event handler.

Thanks again @atomiks 馃帀

Okay I think I found the issue:

You're using @click.stop which stops the click event from propagating up the DOM tree to the document. The document has a global click listener which handles hiding all tooltips on the document that are visible. So, either you can use the hack posted above, or remove @click.stop and replace it with something else.

you saved me

While this gets debugged there is a hack to fix this:
Basically select any showing poppers on the document and hide them before the new one gets shown.

@atomiks, I use the hideAll() method to hide all tooltips. (I needed this because events listed using the FullCalendar library were close together and the new tooltip was occassionally displayed underneath an interactive tooltip.)

onShow(){
    tippy.hideAll({ duration: 0 });
}

Is this a newer method? Are there any issues with using this approach? (It seems to work correctly.)

Also, I noticed that hideAll() isn't listed in the doc with other methods. It's only referenced in the "Misc - Hide tooltips on scroll".

Yeah, Methods only lists tippy instance methods, but static methods should be listed too

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dpatra picture dpatra  路  4Comments

KubaJastrz picture KubaJastrz  路  3Comments

divmgl picture divmgl  路  3Comments

patrickhlauke picture patrickhlauke  路  3Comments

gclark18 picture gclark18  路  4Comments