atomiks / tippyjs

Tooltip, popover, dropdown, and menu library
https://atomiks.github.io/tippyjs/
MIT License
11.92k stars 520 forks source link

What is the recommended way to use tippy to show tooltips and menus when you have a large number of possible targets on the screen? #929

Closed ndaian closed 2 years ago

ndaian commented 3 years ago

Sorry for the long question … :(

I created a stackblitz here: https://stackblitz.com/edit/angular-tippy-many-objects

I have a Gantt chart that has many bars (hundreds). I want to display a tooltip or menu for any bar in the chart. The tooltips are different for every bar. My understanding is that you create a tippy instance for any element you want to have a tooltip/menu. With hundreds of elements that means hundreds of instances and that can potentially be a memory issue.

I am trying to use only one instance and change its target.

So every time when "mouseOver" is triggered I run tippy(target, …) with the default trigger and target = the element that triggered the mouse event, resulting in a new tippy instance. When the mouse leaves the element, I destroy the tippy instance (instance.destroy) on the "onUntrigger" event.

Since I have "interactive" true, if the mouse leaves the html element only a little bit (less than the interactiveBorder size) and goes back over the element a new tippy instance is created because the "mouseOver" event is triggered. I worked around this issue with an internal flag.

When we leave the element for good the instance is destroyed but somehow one of the popper-instances created when you only go outside the element a little bit is not destroyed. Next time when I go over the element I can see in Developer Tools in Elements that there are two <div> data-tippy-root </div>. To work around this issue I also set "instance=undefined".

Now for the menu (onClick event) I need to set the trigger=click on the instance. But with click as a trigger you have to first create the instance and then it will show up/hide when you click. So every time when I create the tooltip-tippy in "mouseOver" I also create another click-tippy instance with "trigger = click". This click-instance is destroyed and set to undefined when the tooltip-instance is destroyed.

Is this the right way to use Tippy with a large number of HTML elements?

Additional question, what do I do about "rightClick" and "doubleClick" events since there isn't a target=onContext/doubleClick? I am thinking of using trigger:manual but I need to figure out how to use it.

atomiks commented 3 years ago

You probably want to use a singleton or delegate to reduce memory impact, both of which have docs on the Addons page

ndaian commented 3 years ago

My understanding after reading about singleton and delegate is that you still have one instance per element. For singleton you pass an array of instances. Do they get destroyed after the singleton is created? In the case of delegate, it will create the instances for you, when needed. Does that mean that if I have 100 element and hover over 10 of them, only 10 instances will be created?

atomiks commented 2 years ago

My understanding after reading about singleton and delegate is that you still have one instance per element. For singleton you pass an array of instances. Do they get destroyed after the singleton is created?

No the instances aren't destroyed.

In the case of delegate, it will create the instances for you, when needed. Does that mean that if I have 100 element and hover over 10 of them, only 10 instances will be created?

Yes that's correct