Add support for <Tippy> as a child (issue #123 in 6.x)
Having <Tippy> as a child of an element to tooltip was a nice use-case in 4.x. See https://github.com/KABBOUCHI/vue-tippy/issues/123. We re-add this in a similar manner. Using to="parent" (as a fixed string), one can now use either the main <Tippy> slot ("default") or its specific "content" slot to specify the tooltip content. The tooltip will be triggered on the parent element without adding a specifc Tippy node to the DOM. This should provides a non-interfering way to specify tooltips. Implementation: For the to="parent" case, we need to find the parent DOM element, but in the "worst" case <Tippy> won't render any DOM nodes at all, which could help us to find the parent. Instead, we initially render a hidden <span> (and the tooltip content). Using the span as a template ref ('findParentHelper'), we can get the parent and assign that to the actual 'elem' ref. This will trigger a re-render, where we can drop the helper <span> again.
This commit is contained in:
@@ -70,6 +70,20 @@ Mount tippy on the child node instead of default tag
|
||||
<template #content>Hi!</template>
|
||||
</tippy>
|
||||
```
|
||||
|
||||
### Example 3
|
||||
Tippy as a child using `to="parent"`. \
|
||||
Works like `:tag="null"`, but applies the tooltip to the parent element instead of the child.
|
||||
|
||||
```html
|
||||
<button>
|
||||
<tippy to="parent" content-tag="div" ontent-class="content-wrapper">
|
||||
Hi!
|
||||
</tippy>
|
||||
Tippy!
|
||||
</button>
|
||||
```
|
||||
|
||||
## Singleton
|
||||
|
||||
### Example 1
|
||||
|
||||
@@ -88,6 +88,33 @@
|
||||
</tippy>
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<span class="font-semibold mr-4">Tippy as a child component with prop content:</span>
|
||||
|
||||
<button class="text-sm py-2 px-3 bg-gray-900 text-white rounded-lg">
|
||||
Hi
|
||||
<tippy to="parent" content="Test"></tippy>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<span class="font-semibold mr-4">Tippy as a child component with #content template:</span>
|
||||
|
||||
<button class="text-sm py-2 px-3 bg-gray-900 text-white rounded-lg">
|
||||
Hi
|
||||
<tippy to="parent"><template #content>Test</template></tippy>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<span class="font-semibold mr-4">Tippy as a child component with direct content:</span>
|
||||
|
||||
<button class="text-sm py-2 px-3 bg-gray-900 text-white rounded-lg">
|
||||
Hi
|
||||
<tippy to="parent">{{counter}} and counting</tippy>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<span class="font-semibold mr-4">useTippy + callbacks(console.log):</span>
|
||||
<button
|
||||
|
||||
+31
-3
@@ -89,6 +89,7 @@ const TippyComponent = defineComponent({
|
||||
emits: ['state'],
|
||||
setup(props, { slots, emit, expose }) {
|
||||
const elem = ref<Element>()
|
||||
const findParentHelper = ref<HTMLElement>()
|
||||
const contentElem = ref<Element>()
|
||||
const mounted = ref(false)
|
||||
|
||||
@@ -109,13 +110,24 @@ const TippyComponent = defineComponent({
|
||||
if (props.to) {
|
||||
if (typeof Element !== 'undefined' && props.to instanceof Element) {
|
||||
target = () => props.to
|
||||
} else if (props.to === 'parent') {
|
||||
target = () => {
|
||||
let el = elem.value
|
||||
if (!el) {
|
||||
el = elem.value = findParentHelper.value!.parentElement as HTMLElement
|
||||
}
|
||||
return el
|
||||
}
|
||||
} else if (typeof props.to === 'string' || props.to instanceof String) {
|
||||
target = () => document.querySelector(props.to as any)
|
||||
}
|
||||
}
|
||||
|
||||
const tippy = useTippy(target, getOptions())
|
||||
const contentSlot = slots.content
|
||||
let contentSlot = slots.content
|
||||
if (!contentSlot && props.to === 'parent') {
|
||||
contentSlot = slots.default
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
mounted.value = true
|
||||
@@ -147,8 +159,6 @@ const TippyComponent = defineComponent({
|
||||
expose(exposed)
|
||||
|
||||
return () => {
|
||||
const slot = slots.default ? slots.default(exposed) : []
|
||||
|
||||
const contentTag = typeof props.contentTag === 'string' ? props.contentTag as string : props.contentTag
|
||||
const content = contentSlot
|
||||
? h(
|
||||
@@ -162,6 +172,24 @@ const TippyComponent = defineComponent({
|
||||
)
|
||||
: null
|
||||
|
||||
if (props.to === 'parent') {
|
||||
const result = []
|
||||
if (!elem.value) {
|
||||
const findParentHelperNode = h('span', {
|
||||
ref: findParentHelper,
|
||||
'data-v-tippy': '',
|
||||
style: { display: 'none' },
|
||||
})
|
||||
result.push(findParentHelperNode)
|
||||
}
|
||||
if (content) {
|
||||
result.push(content)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
const slot = slots.default ? slots.default(exposed) : []
|
||||
if (!props.tag) {
|
||||
const trigger = h(slot[0] as any, {
|
||||
ref: elem, 'data-v-tippy': ''
|
||||
|
||||
Reference in New Issue
Block a user