跳至内容

工具提示

当元素获得键盘焦点或鼠标悬停在其上时,显示与元素相关信息的弹出窗口。
vue
<script setup lang="ts">
import { TooltipArrow, TooltipContent, TooltipPortal, TooltipProvider, TooltipRoot, TooltipTrigger } from 'radix-vue'
import { Icon } from '@iconify/vue'
</script>

<template>
  <TooltipProvider>
    <TooltipRoot>
      <TooltipTrigger
        class="text-grass11 shadow-blackA7 hover:bg-green3 inline-flex h-[35px] w-[35px] items-center justify-center rounded-full bg-white shadow-[0_2px_10px] outline-none focus:shadow-[0_0_0_2px] focus:shadow-black"
      >
        <Icon icon="radix-icons:plus" />
      </TooltipTrigger>
      <TooltipPortal>
        <TooltipContent
          class="data-[state=delayed-open]:data-[side=top]:animate-slideDownAndFade data-[state=delayed-open]:data-[side=right]:animate-slideLeftAndFade data-[state=delayed-open]:data-[side=left]:animate-slideRightAndFade data-[state=delayed-open]:data-[side=bottom]:animate-slideUpAndFade text-grass11 select-none rounded-[4px] bg-white px-[15px] py-[10px] text-[15px] leading-none shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,_hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] will-change-[transform,opacity]"
          :side-offset="5"
        >
          Add to library
          <TooltipArrow
            class="fill-white"
            :width="8"
          />
        </TooltipContent>
      </TooltipPortal>
    </TooltipRoot>
  </TooltipProvider>
</template>

功能

  • 提供者用于全局控制显示延迟。
  • 当触发器获得焦点或悬停时打开。
  • 当触发器被激活或按下 Escape 键时关闭。
  • 支持自定义计时。

解剖学

导入所有部分并将它们拼凑在一起。

vue
<script setup lang="ts">
import { TooltipArrow, TooltipContent, TooltipPortal, TooltipProvider, TooltipRoot, TooltipTrigger } from 'radix-vue'
</script>

<template>
  <TooltipProvider>
    <TooltipRoot>
      <TooltipTrigger />
      <TooltipPortal>
        <TooltipContent>
          <TooltipArrow />
        </TooltipContent>
      </TooltipPortal>
    </TooltipRoot>
  </TooltipProvider>
</template>

API 参考

提供者

包装您的应用程序以向您的工具提示提供全局功能。

道具默认类型
delayDuration
700
number

指针进入触发器到工具提示打开的时间间隔。

disableClosingTrigger
boolean

true 时,单击触发器不会关闭内容。

disabled
boolean

true 时,禁用工具提示

disableHoverableContent
false
boolean

true 时,尝试悬停在内容上会导致工具提示在指针离开触发器时关闭。

ignoreNonKeyboardFocus
false
boolean

如果焦点不是来自键盘,则通过与 :focus-visible 选择器匹配来阻止工具提示打开。如果您想在切换浏览器选项卡或关闭对话框时避免打开它,这很有用。

skipDelayDuration
300
number

用户在进入另一个触发器而不会再次产生延迟之前需要多少时间。

包含工具提示的所有部分。

道具默认类型
defaultOpen
false
boolean

工具提示最初渲染时的打开状态。当您不需要控制其打开状态时使用。

delayDuration
number

覆盖提供给 Provider 的持续时间以自定义特定工具提示的打开延迟。

disableClosingTrigger
boolean

true 时,单击触发器不会关闭内容。

disabled
boolean

true 时,禁用工具提示

disableHoverableContent
boolean

阻止 Tooltip.Content 在悬停时保持打开状态。禁用此功能会对可访问性造成影响。从 Tooltip.Provider 继承。

ignoreNonKeyboardFocus
boolean

如果焦点不是来自键盘,则通过与 :focus-visible 选择器匹配来阻止工具提示打开。如果您想在切换浏览器选项卡或关闭对话框时避免打开它,这很有用。

open
boolean

工具提示的受控打开状态。

发射有效载荷
update:open
[value: boolean]

工具提示的打开状态发生变化时调用的事件处理程序。

插槽(默认)有效载荷
open
boolean

当前打开状态

触发器

切换工具提示的按钮。默认情况下,TooltipContent 会将自身定位在触发器上。

道具默认类型
as
'button'
AsTag | Component

此组件应渲染为的元素或组件。可以被 asChild 覆盖

asChild
boolean

更改为子级传递的默认渲染元素,合并它们的道具和行为。

阅读我们的 组合 指南以了解更多详细信息。

数据属性价值
[data-state]"closed" | "delayed-open" | "instant-open"

传送门

使用时,将内容部分传送到 body 中。

道具默认类型
disabled
boolean

禁用传送并内联渲染组件

reference

forceMount
boolean

用于在需要更多控制时强制安装。在使用 Vue 动画库控制动画时很有用。

to
string | HTMLElement

Vue 原生传送组件道具 :to

reference

内容

工具提示打开时弹出的组件。

道具默认类型
align
'start' | 'center' | 'end'

相对于触发器的首选对齐方式。在发生碰撞时可能会改变。

alignOffset
number

startend 对齐选项的像素偏移量。

ariaLabel
string

默认情况下,屏幕阅读器会宣布组件内部的内容。如果这不够描述,或者您有无法宣布的内容,请使用 aria-label 作为更具描述性的标签。

arrowPadding
number

箭头和内容边缘之间的填充。如果您的内容有边框半径,这将阻止它溢出角落。

as
'div'
AsTag | Component

此组件应渲染为的元素或组件。可以被 asChild 覆盖

asChild
boolean

更改为子级传递的默认渲染元素,合并它们的道具和行为。

阅读我们的 组合 指南以了解更多详细信息。

avoidCollisions
boolean

true 时,覆盖侧面和对齐首选项以防止与边界边缘发生碰撞。

collisionBoundary
Element | (Element | null)[] | null

用作碰撞边界的元素。默认情况下,这是视口,尽管您可以提供要包含在此检查中的其他元素。

collisionPadding
number | Partial<Record<'top' | 'right' | 'bottom' | 'left', number>>

从边界边缘的距离(以像素为单位),在该距离处应发生碰撞检测。接受一个数字(所有边都相同),或一个部分填充对象,例如:{ top: 20, left: 20 }。

forceMount
boolean

用于在需要更多控制时强制安装。在使用 Vue 动画库控制动画时很有用。

hideWhenDetached
boolean

当触发器被完全遮挡时是否隐藏内容。

side
'top'
'top' | 'right' | 'bottom' | 'left'

打开时渲染的触发器首选侧边。当发生碰撞并且启用 avoidCollisions 时,它将被反转。

sideOffset
number

距触发器的距离(以像素为单位)。

sticky
'partial' | 'always'

对齐轴上的粘性行为。partial 将使内容保持在边界内,只要触发器至少部分位于边界内,而 "always" 将使内容无论如何都保持在边界内。

发射有效载荷
escapeKeyDown
[event: KeyboardEvent]

在打开后焦点移动到破坏性操作时调用的事件处理程序。可以通过调用 event.preventDefault 来阻止它。

pointerDownOutside
[event: Event]

在组件边界之外发生指针事件时调用的事件处理程序。可以通过调用 event.preventDefault 来阻止它。

数据属性价值
[data-state]"closed" | "delayed-open" | "instant-open"
[data-side]"left" | "right" | "bottom" | "top"
[data-align]"start" | "end" | "center"
CSS 变量描述
--radix-tooltip-content-transform-origin
从内容和箭头位置/偏移量计算的 transform-origin
--radix-tooltip-content-available-width
触发器和边界边缘之间的剩余宽度
--radix-tooltip-content-available-height
触发器和边界边缘之间的剩余高度
--radix-tooltip-trigger-width
触发器的宽度
--radix-tooltip-trigger-height
触发器的高度

箭头

一个可选的箭头元素,用于与工具提示一起渲染。这可以用来帮助从视觉上将触发器与 TooltipContent 联系起来。必须在 TooltipContent 内渲染。

道具默认类型
as
'svg'
AsTag | Component

此组件应渲染为的元素或组件。可以被 asChild 覆盖

asChild
boolean

更改为子级传递的默认渲染元素,合并它们的道具和行为。

阅读我们的 组合 指南以了解更多详细信息。

height
5
number

箭头的以像素为单位的高度。

width
10
number

箭头的以像素为单位的宽度。

示例

全局配置

使用 Provider 全局控制 delayDurationskipDelayDuration

vue
<script setup>
import { TooltipContent, TooltipProvider, TooltipRoot, TooltipTrigger } from 'radix-vue'
</script>

<template>
  <TooltipProvider
    :delay-duration="800"
    :skip-delay-duration="500"
  >
    <TooltipRoot>
      <TooltipTrigger></TooltipTrigger>
      <TooltipContent></TooltipContent>
    </TooltipRoot>
    <TooltipRoot>
      <TooltipTrigger></TooltipTrigger>
      <TooltipContent></TooltipContent>
    </TooltipRoot>
  </TooltipProvider>
</template>

立即显示

使用 delayDuration 道具来控制工具提示打开所需的时间。

vue
<script setup>
import { TooltipContent, TooltipProvider, TooltipRoot, TooltipTrigger } from 'radix-vue'
</script>

<template>
  <TooltipRoot :delay-duration="0">
    <TooltipTrigger></TooltipTrigger>
    <TooltipContent></TooltipContent>
  </TooltipRoot>
</template>

从禁用按钮显示工具提示

由于禁用的按钮不会触发事件,因此您需要

  • Trigger 渲染为 span
  • 确保 button 没有 pointerEvents
vue
<script setup>
import { TooltipContent, TooltipProvider, TooltipRoot, TooltipTrigger } from 'radix-vue'
</script>

<template>
  <TooltipRoot>
    <TooltipTrigger as-child>
      <span tabindex="0">
        <button
          disabled
          style="{ pointerEvents: 'none' }"
        ></button>
      </span>
    </TooltipTrigger>
    <TooltipContent></TooltipContent>
  </TooltipRoot>
</template>

约束内容大小

您可能希望约束内容的宽度以使其与触发器宽度匹配。您可能还想约束其高度以不超过视口。

我们公开了几个 CSS 自定义属性,例如 --radix-tooltip-trigger-width--radix-tooltip-content-available-height 来支持这一点。使用它们来约束内容尺寸。

vue
 <!-- index.vue -->
<script setup>
import { TooltipContent, TooltipProvider, TooltipRoot, TooltipTrigger } from 'radix-vue'
</script>

<template>
  <TooltipRoot>
    <TooltipTrigger></TooltipTrigger>
    <TooltipPortal>
      <TooltipContent
        class="TooltipContent"
        :side-offset="5"
      >

      </TooltipContent>
    </TooltipPortal>
  </TooltipRoot>
</template>
css
/* styles.css */
.TooltipContent {
  width: var(--radix-tooltip-trigger-width);
  max-height: var(--radix-tooltip-content-available-height);
}

支持原点的动画

我们公开了 CSS 自定义属性 --radix-tooltip-content-transform-origin。使用它根据 sidesideOffsetalignalignOffset 和任何碰撞从其计算出的原点对内容进行动画处理。

vue
 <!-- index.vue -->
<script setup>
import { TooltipContent, TooltipProvider, TooltipRoot, TooltipTrigger } from 'radix-vue'
</script>

<template>
  <TooltipRoot>
    <TooltipTrigger></TooltipTrigger>
    <TooltipContent class="TooltipContent">

    </TooltipContent>
  </TooltipRoot>
</template>
css
/* styles.css */
.TooltipContent {
  transform-origin: var(--radix-tooltip-content-transform-origin);
  animation: scaleIn 0.5s ease-out;
}

@keyframes scaleIn {
  from {
    opacity: 0;
    transform: scale(0);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

支持碰撞的动画

我们公开data-sidedata-align 属性。它们的值将在运行时更改以反映碰撞。使用它们来创建与碰撞和方向感知的动画。

vue
 <!-- index.vue -->
<script setup>
import { TooltipContent, TooltipProvider, TooltipRoot, TooltipTrigger } from 'radix-vue'
</script>

<template>
  <TooltipRoot>
    <TooltipTrigger></TooltipTrigger>
    <TooltipContent class="TooltipContent">

    </TooltipContent>
  </TooltipRoot>
</template>
css
/* styles.css */
.TooltipContent {
  animation-duration: 0.6s;
  animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
}
.TooltipContent[data-side="top"] {
  animation-name: slideUp;
}
.TooltipContent[data-side="bottom"] {
  animation-name: slideDown;
}

@keyframes slideDown {
  from {
    opacity: 0;
    transform: translateY(-10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes slideUp {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

无障碍性

键盘交互

描述
Tab
打开/关闭工具提示,无需延迟。
空格
如果打开,则关闭工具提示,无需延迟。
Enter
如果打开,则关闭工具提示,无需延迟。
Escape
如果打开,则关闭工具提示,无需延迟。

自定义 API

通过将基本部分抽象到您自己的组件中,创建您自己的 API。

抽象部分并引入一个内容属性

此示例抽象了所有Tooltip 部分并引入了一个新的content 属性。

用法

vue
<script setup lang="ts">
import { Tooltip } from './your-tooltip'
</script>

<template>
  <Tooltip content="Tooltip content">
    <button>Tooltip trigger</button>
  </Tooltip>
</template>

实现

使用asChild 属性将触发部分转换为可插槽区域。它将用传递给它的子级替换触发器。

vue
<!-- your-tooltip.vue  -->
<script setup lang="ts">
import { TooltipArrow, TooltipContent, TooltipRoot, type TooltipRootEmits, type TooltipRootProps, TooltipTrigger, useForwardPropsEmits } from 'radix-vue'

const props = defineProps<TooltipRootProps & { content?: string }>()
const emits = defineEmits<TooltipRootEmits>()

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

<template>
  <TooltipRoot v-bind="forward">
    <TooltipTrigger as-child>
      <slot />
    </TooltipTrigger>
    <TooltipContent
      side="top"
      align="center"
    >
      {{ content }}
      <TooltipArrow
        :width="11"
        :height="5"
      />
    </TooltipContent>
  </TooltipRoot>
</template>