Tooltip
It is commonly used to display prompt information when the mouse hover.
Basic Usage
Use placement to set the position of the tooltip, and use content to set the content of the tooltip.
<template>
<div class="max-w-600px mx-auto">
<div class="flex justify-center">
<re-tooltip placement="top-start" content="Top Start Text Prompt">
<re-button>top-start</re-button>
</re-tooltip>
<re-tooltip placement="top" content="Top Center Text Prompt">
<re-button>top</re-button>
</re-tooltip>
<re-tooltip placement="top-end" content="Top End Text Prompt">
<re-button>top-end</re-button>
</re-tooltip>
</div>
<div class="flex justify-between">
<div class="flex flex-col items-start">
<re-tooltip placement="left-start" width="120" content="Left Start Text Prompt">
<re-button>left-start</re-button>
</re-tooltip>
<re-tooltip placement="left" width="120px" content="Left Middle Text Prompt">
<re-button class="mt-1em ml-0!">left</re-button>
</re-tooltip>
<re-tooltip placement="left-end" width="120px" content="Left End Text Prompt">
<re-button class="mt-1em ml-0!">left-end</re-button>
</re-tooltip>
</div>
<div class="flex flex-col items-end">
<re-tooltip placement="right-start" width="120px" content="Right Start Text Prompt">
<re-button>right-start</re-button>
</re-tooltip>
<re-tooltip placement="right" width="120px" content="Right Center Text Prompt">
<re-button class="mt-1em ml-0!">right</re-button>
</re-tooltip>
<re-tooltip placement="right-end" width="120px" content="Right End Text Prompt">
<re-button class="mt-1em ml-0!">right-end</re-button>
</re-tooltip>
</div>
</div>
<div class="flex justify-center">
<re-tooltip placement="bottom-start" content="Bottom Start Text Prompt">
<re-button>bottom-start</re-button>
</re-tooltip>
<re-tooltip placement="bottom" content="Bottom Center Text Prompt">
<re-button>bottom</re-button>
</re-tooltip>
<re-tooltip placement="bottom-end" content="Bottom End Text Prompt">
<re-button>bottom-end</re-button>
</re-tooltip>
</div>
</div>
</template>Trigger
Use hover 、 click 、 focus and contextmenu to display Tooltip by trigger attribute.
<template>
<re-tooltip content="Tooltip text" trigger="hover">
<re-button>Hover</re-button>
</re-tooltip>
<re-tooltip content="Tooltip text" trigger="click">
<re-button>Click</re-button>
</re-tooltip>
<re-tooltip content="Tooltip text" trigger="focus">
<re-button>Focus</re-button>
</re-tooltip>
<re-tooltip content="Tooltip text" trigger="contextmenu" placement="right">
<re-button>Contextmenu</re-button>
</re-tooltip>
</template>Content
Use content or slot#content to set Tooltip content, is-html for render HTML content.
<template>
<re-tooltip content="<i>Text Content</i>" trigger="hover">
<re-button>Text Content</re-button>
</re-tooltip>
<re-tooltip content="<i>HTML Content</i>" is-html trigger="hover">
<re-button>HTML Content</re-button>
</re-tooltip>
<re-tooltip trigger="hover">
<re-button>Slot Content</re-button>
<template #content>
<span style="color: #9d87ff">The Slot Content</span>
</template>
</re-tooltip>
</template>Disabled
Use disabled to disable Tooltip.
<template>
<div>
<re-tooltip :disabled="disabled" content="Disabled tooltip" trigger="hover">
<re-button type="success" :disabled="disabled">
{{ disabled ? 'Disabled' : 'Enabled' }}
</re-button>
</re-tooltip>
<re-button class="ml-5em!" @click="toggle">Click to toggle</re-button>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const disabled = ref(false)
const toggle = () => {
disabled.value = !disabled.value
}
</script>Customize Boundary
Use boundary and rootBoundary to set Tooltip boundary.
<template>
<div>
<div class="flex flex-wrap">
<div
ref="container1"
class="h-300px grow basis-300px of-x-hidden of-y-auto text-center demo-border"
>
<div class="h-300px"></div>
<re-tooltip
v-if="container1"
:boundary="container1"
content="Scroll me to top boundary"
:visible="visible"
>
<re-button>boundary: container</re-button>
</re-tooltip>
<div class="h-300px"></div>
</div>
<div
ref="container2"
class="h-300px grow flex basis-300px items-center of-x-auto demo-border"
>
<div class="w-500px shrink-0"></div>
<re-tooltip
v-if="container2"
content="Scroll me to left boundary"
:boundary="container2"
:visible="visible"
placement="left"
>
<re-button>boundary: container</re-button>
</re-tooltip>
<div class="w-500px shrink-0"></div>
</div>
</div>
<div
ref="container3"
class="h-300px flex-1 of-hidden of-y-auto shrink-0 text-center demo-border"
>
<div class="h-300px"></div>
<re-tooltip content="Scroll me to body top boundary" :visible="visible">
<re-button>rootBoundary: 'viewport'</re-button>
</re-tooltip>
<div class="h-300px"></div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
const visible = ref<boolean>(true)
const container1 = ref()
const container2 = ref()
const container3 = ref()
onMounted(() => {
container1.value.scrollTo(0, 160)
container2.value.scrollTo(220, 0)
container3.value.scrollTo(0, 160)
})
</script>Flip
By default, the Tooltip layer will auto flip based on the viewport, but when one of the below:
1、boundary: 'clippingAncestors' and altBoundary: true.
2、elementContext: 'reference'.
it will flip based on the parent container of the reference which is overflow: hidden/auto/scroll.
Otherwise, use flipOptions attribute for more behaviors.
<template>
<div class="flex flex-wrap">
<div
ref="container1"
class="h-300px grow basis-300px of-hidden of-y-auto shrink-0 text-center demo-border"
>
<div class="h-300px"></div>
<re-tooltip v-model:visible="visible" alt-boundary content="Scroll me to top boundary">
<re-button>altBoundary: true</re-button>
</re-tooltip>
<div class="h-300px"></div>
</div>
<div
ref="container2"
class="h-300px grow basis-300px flex items-center min-w-0 of-x-auto demo-border"
>
<div class="w-500px shrink-0"></div>
<re-tooltip
content="Scroll me to left boundary"
alt-boundary
:visible="visible"
placement="left"
>
<re-button>altBoundary: true</re-button>
</re-tooltip>
<div class="w-500px shrink-0"></div>
</div>
</div>
<div class="flex flex-wrap">
<div
ref="container3"
class="h-300px grow basis-300px of-hidden of-y-auto shrink-0 text-center demo-border"
>
<div class="h-300px"></div>
<re-tooltip
element-context="reference"
content="elementContext: 'reference'"
:visible="visible"
>
<re-button>Scroll me to top boundary</re-button>
</re-tooltip>
<div class="h-300px"></div>
</div>
<div
ref="container4"
class="h-300px grow basis-300px flex items-center min-w-0 of-x-auto demo-border"
>
<div class="w-500px shrink-0"></div>
<re-tooltip
content="elementContext: 'reference'"
element-context="reference"
:visible="visible"
placement="left"
>
<re-button>Scroll me to left boundary</re-button>
</re-tooltip>
<div class="w-500px shrink-0"></div>
</div>
</div>
<div class="flex flex-wrap">
<div
ref="container5"
class="h-300px grow basis-300px of-hidden of-y-auto shrink-0 text-center demo-border"
>
<div class="h-300px"></div>
<re-tooltip
alt-boundary
:flip-options="{ fallbackPlacements: ['top', 'right', 'bottom'] }"
content="Scroll me to top boundary"
:visible="visible"
>
<re-button class="mr-15em">altBoundary: true</re-button>
</re-tooltip>
<div class="h-300px"></div>
</div>
<div
ref="container6"
class="h-300px grow basis-300px flex items-center min-w-0 of-x-auto demo-border"
>
<div class="w-500px shrink-0"></div>
<re-tooltip
content="Scroll me to left boundary"
alt-boundary
:flip-options="{ fallbackPlacements: ['top', 'right', 'bottom'] }"
:visible="visible"
placement="left"
>
<re-button>altBoundary: true</re-button>
</re-tooltip>
<div class="w-500px shrink-0"></div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
const visible = ref<boolean>(true)
const container1 = ref()
const container2 = ref()
const container3 = ref()
const container4 = ref()
const container5 = ref()
const container6 = ref()
onMounted(() => {
container1.value.scrollTo(0, 160)
container2.value.scrollTo(220, 0)
container3.value.scrollTo(0, 160)
container4.value.scrollTo(220, 0)
container5.value.scrollTo(0, 160)
container6.value.scrollTo(220, 0)
})
</script>External Reference
Use is-external to activate external-ref, this allows you to place the reference element outside the Tooltip.
Basic External Trigger Reference
Multiple External Trigger References for singleton
<template>
<p>Basic External Trigger Reference</p>
<re-tooltip
content="Tooltip text"
trigger="hover"
is-external
:external-ref="externalRef"
></re-tooltip>
<re-button ref="buttonRef" @mouseenter="setExternal">Hover me</re-button>
<p>Multiple External Trigger References for singleton</p>
<re-tooltip
content="Tooltip text"
trigger="hover"
is-external
:external-ref="hoverRef"
></re-tooltip>
<re-button ref="buttonRef1" @mouseenter="setRef1()">Hover me 1</re-button>
<re-button ref="buttonRef2" @mouseenter="setRef2()">Hover me 2</re-button>
<re-button ref="buttonRef3" @mouseenter="setRef3()">Hover me 3</re-button>
<p></p>
<re-tooltip
content="Tooltip text"
trigger="click"
is-external
:external-ref="clickRef"
></re-tooltip>
<re-button ref="buttonRef4" @click="setRef4()">Click me 1</re-button>
<re-button ref="buttonRef5" @click="setRef5()">Click me 2</re-button>
<re-button ref="buttonRef6" @click="setRef6()">Click me 3</re-button>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const buttonRef = ref()
const externalRef = ref()
const setExternal = () => {
externalRef.value = buttonRef.value
}
const buttonRef1 = ref()
const buttonRef2 = ref()
const buttonRef3 = ref()
const hoverRef = ref()
const setRef1 = () => {
hoverRef.value = buttonRef1.value
}
const setRef2 = () => {
hoverRef.value = buttonRef2.value
}
const setRef3 = () => {
hoverRef.value = buttonRef3.value
}
const buttonRef4 = ref()
const buttonRef5 = ref()
const buttonRef6 = ref()
const clickRef = ref()
const setRef4 = () => {
clickRef.value = buttonRef4.value
}
const setRef5 = () => {
clickRef.value = buttonRef5.value
}
const setRef6 = () => {
clickRef.value = buttonRef6.value
}
</script>Virtual Reference
Use is-virtual to activate virtual-ref, it accepts an object with layout properties to build the reference, visible maybe is needed.
<template>
<re-tooltip
content="Tooltip text"
:visible="visible"
is-virtual
:virtual-ref="virtualRef"
></re-tooltip>
<re-button @click="visible = !visible">Click me</re-button>
</template>
<script lang="ts" setup>
import { ref, onMounted, onUnmounted } from 'vue'
const visible = ref<boolean>(false)
const position = ref<Record<string, number>>({
width: 0,
height: 0,
x: 0,
y: 0,
top: 0,
left: 0,
right: 0,
bottom: 0
})
const virtualRef = ref({
getBoundingClientRect: () => position.value
})
const move = ({ clientX, clientY }: MouseEvent) => {
position.value = {
width: 0,
height: 0,
x: clientX,
y: clientY,
top: clientY,
left: clientX,
right: clientX,
bottom: clientY
}
}
onMounted(() => {
document.addEventListener('mousemove', move)
})
onUnmounted(() => {
document.removeEventListener('mousemove', move)
})
</script>Selection Range Build A Virtual Reference
Use is-virtual to activate virtual-ref, it also allows a selection Range to build the reference.
<template>
<re-tooltip
content="Tooltip text"
:visible="visible"
is-virtual
:virtual-ref="rangeRef"
></re-tooltip>
<span ref="textRef">Select the text to visible the Tooltip</span>
</template>
<script lang="ts" setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
const visible = ref<boolean>(false)
const textRef = ref<HTMLSpanElement | null>(null)
const range = ref<Range | null>()
const rangeRef = {
getBoundingClientRect: () => range.value?.getBoundingClientRect(),
getClientRects: () => range.value?.getClientRects()
}
const mouseup = () => {
range.value?.selectNode(textRef.value!)
const selection = window.getSelection()
if (!textRef.value || !selection || selection.rangeCount === 0) return
const currentRange = selection.getRangeAt(0)
const container = currentRange.commonAncestorContainer
const text = selection.toString().trim()
// Ensure the selection originates from the target element
if (textRef.value.contains(container!)) {
range.value = currentRange.cloneRange()
visible.value = !!text
}
}
const selectionChange = () => {
const selection = window.getSelection()
const text = selection?.toString()?.trim()
if (!text) {
visible.value = false
}
}
onMounted(() => {
document.addEventListener('mouseup', mouseup)
document.addEventListener('selectionchange', selectionChange)
})
onBeforeUnmount(() => {
document.removeEventListener('mouseup', mouseup)
document.removeEventListener('selectionchange', selectionChange)
})
</script>Tooltip Attributes
| Name | Description | Type | Default |
|---|---|---|---|
| placement | Tooltip position | enum | top |
| trigger | The trigger event name | enum | hover |
| content | Tooltip content | string | — |
| is-html | Whether content is treated as HTML string | boolean | — |
| disabled | Whether Tooltip is disabled | boolean | — |
| visible / v-model:visible | Whether Tooltip is visible | boolean | — |
| offset | Offset from the reference edge | number | 10 |
| width | Tooltip width | number | string | — |
| height | Tooltip height | number | string | — |
| max-width | Tooltip max width | number | string | — |
| max-height | Tooltip max height | number | string | — |
| theme | Tooltip theme | 'dark' |'light' | dark |
| reverse-theme | whether to reverse Tooltip theme color | boolean | false |
| append-to | Target element for appending Tooltip | cssSelector | HTMLElement | body |
| teleported | Whether to teleport Tooltip to the appendTo target | boolean | true |
| persistent | Whether to keep the floating open on hover | boolean | true |
| floating-class | Custom class for the floating | union | — |
| floating-style | Custom style for the floating | union | — |
| show-delay | Delay(ms) before Tooltip appears , but not effective when visible is present or is-virtual or is-external | number | 0 |
| hide-delay | Delay(ms) before Tooltip disappears , but not effective when visible is present or is-virtual or is-external | number | 200 |
| show-arrow | Whether to show arrow for Tooltip | boolean | true |
| arrow-size | The arrow size | number | 8 |
| arrow-offset | Padding between the arrow and the Tooltip edge | number | 4 |
| arrow-options | Floating UI ArrowOptions Parameters | interface | — |
| transition | Name of Vue3 Transition component | string | tooltip |
| css-transition | Css of Vue3 Transition component | boolean | true |
| css-duration | Duration of Vue3 Transition component | number | 0 |
| boundary | Boundary of Floating UI DetectOverflowOptions : interface | union | clippingAncestors |
| alt-boundary | AltBoundary of Floating UI DetectOverflowOptions | boolean | false |
| root-boundary | RootBoundary of Floating UI DetectOverflowOptions | union | viewport |
| element-context | ElementContext of Floating UI DetectOverflowOptions | 'reference' | 'floating' | floating |
| flip-offset | Offset from boundary before flipping, Padding of Floating UI DetectOverflowOptions | union | 8 |
| flip-options | Floating UI FlipOptions Parameters | interface | — |
| inline-options | Floating UI InlineOptions Parameters | interface | — |
| is-external | Whether external reference is enabled | boolean | — |
| external-ref | External reference target | HTMLElement | — |
| is-virtual | Whether virtual reference is enabled | boolean | — |
| virtual-ref | Virtual reference object for Floating UI VirtualElement | interface | — |
Tooltip Slots
| Name | Description |
|---|---|
| default | Customize default reference |
| content | Customize default content |
Tooltip Exposes
| Name | Description | Type |
|---|---|---|
| update | Manually updates the Tooltip position | Function |
| show | Manually show the Tooltip | Function |
| hide | Manually hide the Tooltip | Function |
| triggerRef | The trigger refernce element | HTMLElement |
| floatingRef | The Tooltip layer element | HTMLElement |
| arrowRef | The Tooltip arrow element | HTMLElement |
