KABBOUCHI / vue-tippy

VueJS Tooltip powered by Tippy.js
https://vue-tippy.netlify.app
MIT License
722 stars 86 forks source link

reusing one tippy #315

Open mech01nc01 opened 3 weeks ago

mech01nc01 commented 3 weeks ago

Hello,

i love your lib and i use it widely, but there was one thing i missed so i implemented some sort of "cloning", but that was very very poor and after updating vue to the latest version it broke partly

what i want to do: create a tippy with a component:

<tippy placement="left" <!-- this is the "default" !-->
            :interactive="true"
            :arrow="true"
            maxWidth="none"
            trigger="click"
            clone="group1">
        <!-- Content -->
        <template #content>
            <myCompoent :objId="selectedId" />
        </template>
</tippy>

as you can see, this tippy has no trigger, its just a "content-tippy" now, i can do somehting like:

<div @click="selectedId=id" v-tippy="{ clone: 'group1', trigger: 'click' /* trigger gets overwritten, although its the same as in content-tippy */ }">
<div @click="selectedId=id" v-tippy="{ clone: 'group1', trigger: 'click' }">
<div @click="selectedId=id" v-tippy="{ clone: 'group1', trigger: 'click' }">
<div @click="selectedId=id" v-tippy="{ clone: 'group1', trigger: 'click' }">
<div @click="selectedId=id" v-tippy="{ clone: 'group1', trigger: 'click' }">
.... and so on, assume 100+ elements

now for every element, the one and only tippy will be reused, without creating new instances

is something like this already possible or would it be possible to implement?

why? i often use it for additional information in large lists, sometimes loading also additional data within the component lets assume a list of 100 entries with 2 tippys per row, one static, one loads additional data this results in 200 additional vue-components and 100 additional requests to the server

instead i would like to have just 2 additional vue-components and 1 request (plus more requests if the props of the components that loads async data change)

mech01nc01 commented 3 weeks ago

or in other words: i would like to have 1 tippy with multiple targets and the tippy will just be moved to the current target ;)

mech01nc01 commented 3 weeks ago

lwPop.zip i now have a working current version for me, these are basicly copies from your files but with some additions, it may break something i do not use or so, don't know, but at least it works the way i need ;) maybe this could show what i wanted to describe in the first post

usage:

this will be placed somewhere at the beginning (it does not really render something)

<lw-pop placement="right"
    :interactive="true"
    :openDelay="1000"
    trigger="click"
    :maxWidth="600"
    clone="group1">
    <template #content>
        <objPreview :id="previewObject.id" />
    </template>
</lw-pop>

now in my rows i use:

<span @click="previewObject=object">
    <div v-lwpop="{ clone: 'group1', trigger: 'click' }">{{ object.name}}</div>
</div>
KABBOUCHI commented 3 weeks ago

@mech01nc01 sry for the late reply

1- u can use singleton, this way they all have the same config https://vue-tippy.netlify.app/flavor/component#singleton 2- conditionally render the content, using state.isShown (u might need to add Suspense)

<tippy>
   <template #content="{ state}">
        <myCompoent v-if="state.isShown" />
   </template>
</tippy>

3- you could create 1 custom instance, show them conditionally when they are on top of the buttons (onShow: () => false), and change the content dynamically depend on which btn u are on, check https://vue-tippy.netlify.app/examples/advanced-follow-mouse

my recommendation is to apply (2) as a quick fix, then try to apply (1) or maybe (3)

edit: a quick PoC: https://codesandbox.io/p/sandbox/vue-tippy-follow-mouse-forked-lhc8kd?file=%2Fsrc%2FApp.vue%3A54%2C24

mech01nc01 commented 2 weeks ago

thanks for your reply, will test. unfortunately your codesandbox link is not working :(

KABBOUCHI commented 2 weeks ago

Made it public

Roxanoel commented 2 weeks ago

Hi, I'm running into a somewhat similar issue. I am using the composition API version of Singleton, and when I do exactly as in the example (using useSingleton, storing refs as an array, and using v-tippy to specify the text to render inside the tooltip), it works as intended. However, I am neither able to use the content option (inside useSingleton) to set the content (it doesn't work even with text), and I am not able to render anything other than text with the v-tippy attribute. Is that behaviour intended? Are singletons only supposed to render plain text, or is there a special way to get them to render my Vue component?

KABBOUCHI commented 2 weeks ago

Hi, I'm running into a somewhat similar issue. I am using the composition API version of Singleton, and when I do exactly as in the example (using useSingleton, storing refs as an array, and using v-tippy to specify the text to render inside the tooltip), it works as intended. However, I am neither able to use the content option (inside useSingleton) to set the content (it doesn't work even with text), and I am not able to render anything other than text with the v-tippy attribute. Is that behaviour intended? Are singletons only supposed to render plain text, or is there a special way to get them to render my Vue component?

plz share a reproduction link on https://vue.new/, and will help u figure that out

u can already use components https://vue-tippy.netlify.app/flavor/component/#singleton, which uses useSingleton internally

I am not able to render anything other than text with the v-tippy attribute

try v-tippy="{ allowHTML: true, content: '<b>Test</b>' }"