Tooltip

TooltipGitHub
A popup that reveals information when hovering over an element.

Usage

Use a Button or any other component in the default slot of the Tooltip.

<template>
  <PTooltip text="Open on GitHub">
    <PButton label="Open" color="neutral" variant="subtle" />
  </PTooltip>
</template>
Make sure to wrap your app with the App component which uses the TooltipProvider component from Akar.
You can check the App component tooltip prop to see how to configure the Tooltip globally.

Text

Use the text prop to set the content of the Tooltip.

<template>
  <PTooltip text="Open on GitHub">
    <PButton label="Open" color="neutral" variant="subtle" />
  </PTooltip>
</template>

Kbds

Use the kbds prop to render Kbd components in the Tooltip.

<template>
  <PTooltip text="Open on GitHub" :kbds="['meta', 'G']">
    <PButton label="Open" color="neutral" variant="subtle" />
  </PTooltip>
</template>
You can use special keys like meta that displays as ⌘ on macOS and Ctrl on other platforms.

Delay

Use the delay-duration prop to change the delay before the Tooltip appears. For example, you can make it appear instantly by setting it to 0.

<template>
  <PTooltip :delay-duration="0" text="Open on GitHub">
    <PButton label="Open" color="neutral" variant="subtle" />
  </PTooltip>
</template>
This can be configured globally through the tooltip.delayDuration option in the App component.

Content

Use the content prop to control how the Tooltip content is rendered, like its align or side for example.

This can be configured globally through the tooltip.content option in the App component.
<template>
  <PTooltip
    :content="{
      align: 'center',
      side: 'bottom',
      sideOffset: 8
    }"
    text="Open on GitHub"
  >
    <PButton label="Open" color="neutral" variant="subtle" />
  </PTooltip>
</template>

Arrow

Use the arrow prop to display an arrow on the Tooltip.

<template>
  <PTooltip arrow text="Open on GitHub">
    <PButton label="Open" color="neutral" variant="subtle" />
  </PTooltip>
</template>

Disabled

Use the disabled prop to disable the Tooltip.

<template>
  <PTooltip disabled text="Open on GitHub">
    <PButton label="Open" color="neutral" variant="subtle" />
  </PTooltip>
</template>

Examples

Control open state

You can control the open state by using the default-open prop or the v-model:open directive.

<script setup lang="ts">
const open = ref(false);

defineShortcuts({
  o: () => open.value = !open.value,
});
</script>

<template>
  <PTooltip
    v-model:open="open"
    text="Open on GitHub"
  >
    <PButton
      label="Open"
      color="neutral"
      variant="subtle"
    />
  </PTooltip>
</template>
<script setup lang="ts">
import { ref } from 'vue'

const open = ref(false);

defineShortcuts({
  o: () => open.value = !open.value,
});
</script>

<template>
  <PTooltip
    v-model:open="open"
    text="Open on GitHub"
  >
    <PButton
      label="Open"
      color="neutral"
      variant="subtle"
    />
  </PTooltip>
</template>
In this example, leveraging defineShortcuts, you can toggle the Tooltip by pressing O.

With following cursor

You can make the Tooltip follow the cursor when hovering over an element using the reference prop:

Hover me
<script setup lang="ts">
const open = ref(false);
const anchor = ref({ x: 0, y: 0 });

const reference = computed(() => ({
  getBoundingClientRect: () =>
    ({
      width: 0,
      height: 0,
      left: anchor.value.x,
      right: anchor.value.x,
      top: anchor.value.y,
      bottom: anchor.value.y,
      ...anchor.value,
    } as DOMRect),
}));
</script>

<template>
  <PTooltip
    :open="open"
    :reference="reference"
    :content="{ side: 'top', sideOffset: 16, updatePositionStrategy: 'always' }"
  >
    <div
      class="text-sm border border-border-accented rounded-md border-dashed flex w-72 aspect-video items-center justify-center"
      @pointerenter="open = true"
      @pointerleave="open = false"
      @pointermove="(ev: PointerEvent) => {
        anchor.x = ev.clientX
        anchor.y = ev.clientY
      }"
    >
      Hover me
    </div>

    <template #content>
      {{ anchor.x.toFixed(0) }} - {{ anchor.y.toFixed(0) }}
    </template>
  </PTooltip>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'

const open = ref(false);
const anchor = ref({ x: 0, y: 0 });

const reference = computed(() => ({
  getBoundingClientRect: () =>
    ({
      width: 0,
      height: 0,
      left: anchor.value.x,
      right: anchor.value.x,
      top: anchor.value.y,
      bottom: anchor.value.y,
      ...anchor.value,
    } as DOMRect),
}));
</script>

<template>
  <PTooltip
    :open="open"
    :reference="reference"
    :content="{ side: 'top', sideOffset: 16, updatePositionStrategy: 'always' }"
  >
    <div
      class="text-sm border border-border-accented rounded-md border-dashed flex w-72 aspect-video items-center justify-center"
      @pointerenter="open = true"
      @pointerleave="open = false"
      @pointermove="(ev: PointerEvent) => {
        anchor.x = ev.clientX
        anchor.y = ev.clientY
      }"
    >
      Hover me
    </div>

    <template #content>
      {{ anchor.x.toFixed(0) }} - {{ anchor.y.toFixed(0) }}
    </template>
  </PTooltip>
</template>

API

Props

Prop Default Type
text
string

The text content of the tooltip.

kbds
(string | undefined)[] | KbdProps[]

The keyboard keys to display in the tooltip.

content
{ side: 'bottom', sideOffset: 8, collisionPadding: 8 }
TooltipContentProps & Partial<EmitsToProps<TooltipContentImplEmits>>

The content of the tooltip.

Inherits from the tooltip.content of the component when not provided.

arrow
false
boolean | TooltipArrowProps

Display an arrow alongside the tooltip. { rounded: true }

portal
true
string | false | true | HTMLElement

Render the tooltip in a portal.

reference
Element | VirtualElement

The reference (or anchor) element that is being referred to for positioning.

If not provided will use the current component as anchor.

defaultOpen
boolean

The open state of the tooltip when it is initially rendered. Use when you do not need to control its open state.

open
boolean

The controlled open state of the tooltip.

delayDuration
700
number

Override the duration given to the Provider to customise the open delay for a specific tooltip.

disableHoverableContent
boolean

Prevents Tooltip.Content from remaining open when hovering. Disabling this has accessibility consequences. Inherits from Tooltip.Provider.

disableClosingTrigger
false
boolean

When true, clicking on trigger will not close the content.

disabled
false
boolean

When true, disable tooltip

ignoreNonKeyboardFocus
false
boolean

Prevent the tooltip from opening if the focus did not come from the keyboard by matching against the :focus-visible selector. This is useful if you want to avoid opening it when switching browser tabs or closing a dialog.

ui
{ content?: SlotClass; arrow?: SlotClass; text?: SlotClass; kbds?: SlotClass; kbdsSize?: SlotClass; }

Slots

Slot Type
default
{ open: boolean; }
content
{ ui: object; }

Emits

Event Type
update:open
[value: boolean]

Theme

app.config.ts
export default defineAppConfig({
  ui: {
    tooltip: {
      slots: {
        content: 'text-xs color-text-highlighted px-2.5 py-1 rounded-sm bg-background flex gap-1 h-6 max-w-[400px] pointer-events-auto select-none ring ring-border shadow-sm origin-$akar-tooltip-content-transform-origin items-center data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
        arrow: 'fill-background stroke-border',
        text: 'truncate',
        kbds: "shrink-0 gap-0.5 hidden items-center lg:inline-flex not-first-of-type:before:me-0.5 not-first-of-type:before:content-['·']",
        kbdsSize: 'sm'
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from 'pohon-ui/vite'

export default defineConfig({
  plugins: [
    vue(),
    ui({
      ui: {
        tooltip: {
          slots: {
            content: 'text-xs color-text-highlighted px-2.5 py-1 rounded-sm bg-background flex gap-1 h-6 max-w-[400px] pointer-events-auto select-none ring ring-border shadow-sm origin-$akar-tooltip-content-transform-origin items-center data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
            arrow: 'fill-background stroke-border',
            text: 'truncate',
            kbds: "shrink-0 gap-0.5 hidden items-center lg:inline-flex not-first-of-type:before:me-0.5 not-first-of-type:before:content-['·']",
            kbdsSize: 'sm'
          }
        }
      }
    })
  ]
})

Changelog

No recent changes