๐ŸŸข Tooltip

  • Provider to control display delay globally.
  • Opens when the trigger is focused or hovered.
  • Closes when the trigger is activated or when pressing escape.
  • Supports custom timings.

Basic

use NTooltip to provide information for a component.

PropDefaultTypeDescription
content-stringSet the tooltip content.
disabled-booleanSet to disable the tooltip.
<template>
  <div class="grid h-28 place-items-center">
    <NTooltip
      content="Hello from tooltip"
    >
      <NButton btn="solid-white">
        Hover me
      </NButton>
    </NTooltip>
  </div>
</template>

Color

tooltip="{color}" is used to set the color of the tooltip.

PropDefaultTypeDescription
tooltipblackstringSet the tooltip color.
You can use any color provided by the Tailwind CSS color palette. You can also add your own colors to the palette through the Configuration section.
<template>
  <div class="h-28 flex flex-wrap items-center justify-around gap-4">
    <NTooltip
      tooltip="black"
      content="The color is black"
    >
      <NButton
        btn="solid-black"
        label="Black"
      />
    </NTooltip>

    <NTooltip
      tooltip="white"
      content="The color is white"
    >
      <NButton
        btn="solid-white"
        label="White"
      />
    </NTooltip>

    <NTooltip
      tooltip="gray"
      content="The color is gray"
    >
      <NButton
        btn="solid-gray"
        label="Gray"
      />
    </NTooltip>

    <NTooltip
      tooltip="primary"
      content="The color is primary"
    >
      <NButton
        btn="solid-primary"
        label="Primary"
      />
    </NTooltip>

    <NTooltip
      tooltip="error"
      content="The color is error"
    >
      <NButton
        btn="solid-error"
        label="Error"
      />
    </NTooltip>

    <NTooltip
      tooltip="warning"
      content="The color is warning"
    >
      <NButton
        btn="solid-warning"
        label="Warning"
      />
    </NTooltip>
  </div>
</template>

Size

PropDefaultTypeDescription
sizexsstringSet the tooltip general size.
You can adjust the tooltip size using any value, including breakpoints (e.g., sm:sm, xs:lg) and states (e.g., hover:lg, focus:3xl).
<template>
  <div class="h-28 flex items-center justify-around">
    <NTooltip
      content="The xs size"
      size="xs"
    >
      <NButton btn="solid-white">
        XS
      </NButton>
    </NTooltip>
    <NTooltip
      content="The sm size"
      size="sm"
    >
      <NButton btn="solid-white">
        SM
      </NButton>
    </NTooltip>
    <NTooltip
      content="The md size"
      size="md"
    >
      <NButton btn="solid-white">
        MD
      </NButton>
    </NTooltip>
    <NTooltip
      content="The lg size"
      size="lg"
    >
      <NButton btn="solid-white">
        LG
      </NButton>
    </NTooltip>
  </div>
</template>

Provider

Configure the tooltip provider using the _tooltipProvider prop.

PropDefaultTypeDescription
delayDuration600numberSet the delay duration of the tooltip.
disableClosingTrigger-booleanWhen true, clicking on trigger will not close the content.
disableHoverableContentfalsebooleanWhen true, trying to hover the content will result in the tooltip closing as the pointer leaves the trigger.
disabled-booleanSet to disable the tooltip.
For more props and information, please refer to the Radix Tooltip Provider documentation.
<template>
  <div class="grid h-28 place-items-center">
    <NTooltip
      content="Hello from tooltip"
      :_tooltip-provider="{
        delayDuration: 0,
        disableClosingTrigger: true,
        disableHoverableContent: true,
      }"
    >
      <NButton btn="solid-white">
        No delay tooltip
      </NButton>
    </NTooltip>
  </div>
</template>

Root

Configure the tooltip root using the _tooltipRoot prop.

PropDefaultTypeDescription
defaultOpenfalsebooleanSet the default open state of the tooltip.
openfalsebooleanSet the open state of the tooltip.
onUpdate:open-voidEvent handler called when the open state of the tooltip changes.
For more props and information, please refer to the Radix Tooltip Root documentation.
<template>
  <div class="grid h-28 place-items-center">
    <NTooltip
      content="Hello from tooltip"
      :_tooltip-root="{
        'onUpdate:open': (value: boolean) => {
          console.log('open', value)
        },
      }"
    >
      <NButton btn="solid-white">
        Hover me
      </NButton>
    </NTooltip>
  </div>
</template>

Content

Configure the tooltip content using the _tooltipContent prop.

PropDefaultTypeDescription
aligncenterstart end centerSet the alignment of the tooltip content.
sidetoptop right bottom leftSet the side of the tooltip content.
sideOffset-numberSet the offset of the tooltip content.
alignOffset-numberSet the offset of the tooltip content.
For more props and information, please refer to the Radix Tooltip Content documentation.
<template>
  <div class="h-28 flex items-center justify-around">
    <NTooltip
      content="A tooltip content"
      :_tooltip-content="{
        side: 'top',
        align: 'start',
        sideOffset: 15,
      }"
    >
      <NButton btn="solid-white">
        Top
      </NButton>
    </NTooltip>

    <NTooltip
      content="A tooltip content"
      :_tooltip-content="{
        side: 'bottom',
        align: 'end',
        sideOffset: 20,
        alignOffset: 100,
      }"
    >
      <NButton btn="solid-white">
        Bottom
      </NButton>
    </NTooltip>

    <NTooltip
      content="A tooltip content"
      :_tooltip-content="{
        side: 'right',
        align: 'center',
      }"
    >
      <NButton btn="solid-white">
        Right
      </NButton>
    </NTooltip>
    <NTooltip
      content="A tooltip content"
      :_tooltip-content="{
        side: 'left',
        align: 'end',
      }"
    >
      <NButton btn="solid-white">
        Left
      </NButton>
    </NTooltip>
  </div>
</template>

Slots

You can use the following slots to customize the tooltip.

NameDescription
defaultThe trigger slot.
contentThe content slot.
<template>
  <NTooltip
    :_tooltip-content="{
      side: 'right',
    }"
  >
    <template #default>
      <NTooltipTrigger
        class="rounded-full p-1"
      >
        <NAvatar
          src="https://avatars.githubusercontent.com/u/499550?v=4"
        />
      </NTooltipTrigger>
    </template>

    <template #content>
      <div class="flex items-center gap-2">
        <NAvatar
          src="https://avatars.githubusercontent.com/u/499550?v=4"
        />
        <div class="flex flex-col">
          <span class="text-sm font-medium">Evan You</span>
          <span class="text-xs text-gray-500">evan@vuejs.org</span>
        </div>
      </div>
    </template>
  </NTooltip>
</template>

Props

import type { TooltipContentProps, TooltipProviderProps, TooltipRootProps, TooltipTriggerProps } from 'radix-vue'
import type { HTMLAttributes } from 'vue'
import type { NButtonProps } from './button'

interface BaseExtensions {
  class?: HTMLAttributes['class']
  size?: HTMLAttributes['class']
}

type TriggerExtensions = NButtonProps & TooltipTriggerProps
type ContentExtensions = BaseExtensions & TooltipContentProps

export interface NTooltipProps extends BaseExtensions {
  /**
   * Disable the tooltip.
   */
  disabled?: boolean
  /**
   * Add a content of the tooltip.
   */
  content?: string
  /**
   * Allows you to add `UnaUI` tooltip preset properties,
   * Think of it as a shortcut for adding options or variants to the preset if available.
   *
   * @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/tooltip.ts
   * @example
   * tooltip="green"
   */
  tooltip?: HTMLAttributes['class']

  // subcomponents
  _tooltipProvider?: Partial<NTooltipProviderProps>
  _tooltipRoot?: Partial<NTooltipRootProps>
  _tooltipTrigger?: Partial<NTooltipTriggerProps>
  _tooltipContent?: Partial<NTooltipContentProps>

  una?: NTooltipUnaProps
}

export interface NTooltipRootProps extends TooltipRootProps {
  'onUpdate:open'?: (value: boolean) => void
}

export interface NTooltipProviderProps extends TooltipProviderProps {
}

export interface NTooltipTriggerProps extends TriggerExtensions {
}

export interface NTooltipContentProps extends ContentExtensions {
  /**
   * Allows you to add `UnaUI` tooltip preset properties,
   * Think of it as a shortcut for adding options or variants to the preset if available.
   *
   * @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/tooltip.ts
   * @example
   * tooltip="green"
   */
  tooltip?: HTMLAttributes['class']

  /**
   * `UnaUI` preset configuration
   *
   * @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/tooltip.ts
   */
  una?: NTooltipUnaProps['tooltipContent']
}

interface NTooltipUnaProps {
  /** CSS class for the tooltip content */
  tooltipContent?: HTMLAttributes['class']
}

Presets

import type { RuleContext } from '@unocss/core'
import type { Theme } from '@unocss/preset-uno'
import { parseColor } from '@unocss/preset-mini/utils'

type TooltipPrefix = 'tooltip'

export const staticTooltip: Record<`${TooltipPrefix}-${string}`, string> = {
  'tooltip-content': 'z-50 overflow-hidden rounded-md px-0.75em py-0.375em text-xs shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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',

  'tooltip-white': 'border border-base bg-popover text-popover',
  'tooltip-black': 'border border-foreground bg-popover-foreground text-popover-foreground',
}

export const dynamicTooltip = [
  [/^tooltip-(.*)$/, ([, c]: string[], { theme }: RuleContext<Theme>) => {
    const color = parseColor(c, theme)
    if ((color?.cssColor?.type === 'rgb' || color?.cssColor?.type === 'rgba') && color.cssColor.components)
      return `bg-${c}-100 border-${c}-50 text-${c}-800 dark:bg-${c}-800 dark:border-${c}-800 dark:text-${c}-100`
  }],
]

export const tooltip = [
  ...dynamicTooltip,
  staticTooltip,
]

Components

You can use any sub-components of NTooltip, such as NTooltipTrigger, NTooltipContent, which are defined in the Radix Tooltip documentation. For more information, please refer to the Radix Tooltip documentation.

<script setup lang="ts">
import type { TooltipRootEmits } from 'radix-vue'
import type { NTooltipProps } from '../../../types'
import { useForwardPropsEmits } from 'radix-vue'

import TooltipContent from './TooltipContent.vue'
import TooltipProvider from './TooltipProvider.vue'
import TooltipRoot from './TooltipRoot.vue'
import TooltipTrigger from './TooltipTrigger.vue'

defineOptions({
  inheritAttrs: false,
})

const props = defineProps<NTooltipProps>()
const emits = defineEmits<TooltipRootEmits>()

const forwarded = useForwardPropsEmits(props, emits)
</script>

<template>
  <TooltipProvider
    v-bind="_tooltipProvider"
    :disabled
  >
    <TooltipRoot
      v-bind="_tooltipRoot"
    >
      <TooltipTrigger
        as-child
        v-bind="_tooltipTrigger"
      >
        <slot />
      </TooltipTrigger>

      <TooltipContent
        v-if="$slots.content || content"
        v-bind="forwarded._tooltipContent"
        :size
        :tooltip
        :disabled
        :una="forwarded.una?.tooltipContent"
      >
        <slot name="content">
          {{ content }}
        </slot>
      </TooltipContent>
    </TooltipRoot>
  </TooltipProvider>
</template>
<script setup lang="ts">
import type { TooltipRootEmits } from 'radix-vue'
import type { NTooltipRootProps } from '../../../types'
import { TooltipRoot, useForwardPropsEmits } from 'radix-vue'

const props = defineProps<NTooltipRootProps>()
const emits = defineEmits<TooltipRootEmits>()

const forwarded = useForwardPropsEmits(props, emits)
</script>

<template>
  <TooltipRoot v-bind="forwarded">
    <slot />
  </TooltipRoot>
</template>
<script setup lang="ts">
import type { TooltipContentEmits } from 'radix-vue'
import type { NTooltipContentProps } from '../../../types'
import { TooltipContent, TooltipPortal, useForwardPropsEmits } from 'radix-vue'
import { computed } from 'vue'
import { cn } from '../../../utils'

defineOptions({
  inheritAttrs: false,
})

const props = withDefaults(defineProps<NTooltipContentProps>(), {
  sideOffset: 4,
  tooltip: 'black',
})

const emits = defineEmits<TooltipContentEmits>()

const delegatedProps = computed(() => {
  const { class: _, ...delegated } = props

  return delegated
})

const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>

<template>
  <TooltipPortal>
    <TooltipContent
      v-bind="{ ...forwarded, ...$attrs }"
      :class="cn(
        'tooltip-content',
        props.class,
        props.una?.tooltipContent,
      )"
      :tooltip
    >
      <slot />
    </TooltipContent>
  </TooltipPortal>
</template>
<script setup lang="ts">
import type { NTooltipProviderProps } from '../../../types'
import { TooltipProvider } from 'radix-vue'

const props = withDefaults(defineProps<NTooltipProviderProps>(), {
  delayDuration: 600,
})
</script>

<template>
  <TooltipProvider v-bind="props">
    <slot />
  </TooltipProvider>
</template>
<script setup lang="ts">
import type { NTooltipTriggerProps } from '../../../types'
import { TooltipTrigger } from 'radix-vue'

const props = defineProps<NTooltipTriggerProps>()
</script>

<template>
  <TooltipTrigger v-bind="props">
    <slot />
  </TooltipTrigger>
</template>