Tooltip
在悬停或聚焦时显示简短说明,不挤动周围内容。
适用场景
- 当界面需要以下行为时使用 Tooltip:在悬停或聚焦时显示简短说明,不挤动周围内容。
安装
选择安装方式,用法示例将同步更新导入路径。
$ bunx --bun shadcn-vue@2.8.2 add https://orvui.efu.me/r/tooltip.json
此示例还需要:
终端
pnpm add lucide-vue-next@^0.468.0首次使用时,将安装的 src/components/orvui/styles.css 导入项目样式入口。
示例
默认
tooltip.vue为单个触发器提供简短标签,并选择显示方向与箭头。
Hover or focus. Press Esc to dismiss.
packages/vue/src/motion/tooltip/examples/default.vue
<script setup lang="ts">
import { ArrowUp, ArrowDown, ArrowLeft, ArrowRight } from "lucide-vue-next";
import { Tooltip, type TooltipSide } from "@/components/orvui/motion/tooltip";
const positions = [
["top", "Top", ArrowUp, "col-start-2 row-start-1"],
["left", "Left", ArrowLeft, "col-start-1 row-start-2"],
["right", "Right", ArrowRight, "col-start-3 row-start-2"],
["bottom", "Bottom", ArrowDown, "col-start-2 row-start-3"],
].map(([side, label, icon, position]) => ({
side: side as TooltipSide,
label: label as string,
icon,
position: position as string,
}));
</script>
<template>
<div class="flex w-full flex-col items-center gap-8 py-6">
<div class="grid grid-cols-3 gap-x-3 gap-y-5">
<Tooltip
v-for="placement in positions"
:key="placement.side"
content="More context"
:side="placement.side"
arrow
><button
type="button"
:class="[
placement.position,
'inline-flex h-10 w-20 items-center justify-center gap-1.5 rounded-lg border border-border bg-card text-xs font-medium text-foreground transition-colors hover:bg-muted focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ring',
]"
>
<component
:is="placement.icon"
aria-hidden="true"
class="size-3.5 text-muted-foreground"
/>{{ placement.label }}
</button></Tooltip
>
</div>
<p class="text-center text-xs text-muted-foreground">
Hover or focus. Press Esc to dismiss.
</p>
</div>
</template>
packages/vue/src/motion/tooltip/src/Tooltip.vue
Toolbar
toolbar.vue在工具栏提示之间共享时序,并为仅图标控件提供名称。
The first label waits, the next ones open instantly. Click hides it until the pointer leaves.
packages/vue/src/motion/tooltip/examples/toolbar.vue
<script setup lang="ts">
import { ref } from "vue";
import { Bold, Italic, Link2, Strikethrough, Underline } from "lucide-vue-next";
import { cn } from "@/components/orvui/lib/utils";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/orvui/motion/tooltip";
const selected = ref(new Set(["bold"]));
const actions = [
{ id: "bold", label: "Bold", shortcut: "⌘B", keys: "Meta+B", icon: Bold },
{
id: "italic",
label: "Italic",
shortcut: "⌘I",
keys: "Meta+I",
icon: Italic,
},
{
id: "underline",
label: "Underline",
shortcut: "⌘U",
keys: "Meta+U",
icon: Underline,
},
{
id: "strike",
label: "Strikethrough",
shortcut: "⌘⇧X",
keys: "Meta+Shift+X",
icon: Strikethrough,
},
];
function toggle(id: string) {
const next = new Set(selected.value);
if (next.has(id)) next.delete(id);
else next.add(id);
selected.value = next;
}
</script>
<template>
<TooltipProvider :delay="300" :skip-delay="400"
><div class="flex w-full flex-col items-center gap-8 py-6">
<div
class="flex items-center gap-1 rounded-xl border border-border bg-card p-1"
>
<Tooltip v-for="action in actions" :key="action.id" as-label
><TooltipTrigger
:aria-pressed="selected.has(action.id)"
:aria-keyshortcuts="action.keys"
:class="
cn(
'grid size-8 place-items-center rounded-lg text-muted-foreground outline-none transition-colors hover:bg-muted hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring',
selected.has(action.id) && 'bg-muted text-foreground',
)
"
@click="toggle(action.id)"
><component
:is="action.icon"
aria-hidden="true"
class="size-4" /></TooltipTrigger
><TooltipContent side="bottom" arrow
><span class="flex items-center gap-2"
>{{ action.label
}}<span
aria-hidden="true"
class="text-[10px] text-muted-foreground"
>{{ action.shortcut }}</span
></span
></TooltipContent
></Tooltip
><span aria-hidden="true" class="mx-1 h-5 w-px bg-border" /><Tooltip
as-label
:disabled="selected.size === 0"
><TooltipTrigger
:disabled="selected.size === 0"
class="grid size-8 place-items-center rounded-lg text-muted-foreground outline-none transition-colors hover:bg-muted hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-40"
><Link2 aria-hidden="true" class="size-4" /></TooltipTrigger
><TooltipContent side="bottom" align="end" arrow
>Insert link</TooltipContent
></Tooltip
>
</div>
<p class="max-w-xs text-center text-xs text-muted-foreground">
The first label waits, the next ones open instantly. Click hides it
until the pointer leaves.
</p>
</div></TooltipProvider
>
</template>
packages/vue/src/motion/tooltip/src/Tooltip.vue
状态与事件
需要由表单、路由或父组件管理时,绑定下列状态并接收对应更新。v-model 是属性与 update 事件的简写;值的类型应与 API 一致。
| 组件 | Vue 绑定 | 更新事件 |
|---|---|---|
Tooltip | v-model:openboolean | update:open |
可选受控属性未传入时,按组件文档的默认行为工作;不要用固定的 false 或空值代替未传入。异步请求和持久化在应用中处理,再把结果传回组件。
API 参考
默认
Tooltip
content?boolean | null | string | number | void | VNode<RendererNode, RendererElement, { [key: string]: any; }> | VNodeArrayChildrenundefinedopen?booleanundefineddefaultOpen?booleanfalsedelay?numbertiming.value.delaycloseDelay?numbertiming.value.closeDelaydisabled?booleanfalseasLabel?booleanfalsefollowCursor?booleanfalseanchorRef?null | HTMLElement | SVGElement | Ref<TooltipAnchor | null, TooltipAnchor | null>—id?stringuseId()side?"top" | "bottom" | "left" | "right"—align?"start" | "center" | "end"—sideOffset?number—arrow?booleanfalseanchorPoint?TooltipPoint—事件
update:open—@update:openopenChange—@openChange插槽
default() => VNodeChild#defaultTooltipContent
side?"top" | "bottom" | "left" | "right""top"align?"start" | "center" | "end""center"sideOffset?number(point ? 12 : 8)arrow?booleanfalseanchorPoint?TooltipPoint—插槽
default() => VNodeChild#defaultToolbar
Tooltip
content?boolean | null | string | number | void | VNode<RendererNode, RendererElement, { [key: string]: any; }> | VNodeArrayChildrenundefinedopen?booleanundefineddefaultOpen?booleanfalsedelay?numbertiming.value.delaycloseDelay?numbertiming.value.closeDelaydisabled?booleanfalseasLabel?booleanfalsefollowCursor?booleanfalseanchorRef?null | HTMLElement | SVGElement | Ref<TooltipAnchor | null, TooltipAnchor | null>—id?stringuseId()side?"top" | "bottom" | "left" | "right"—align?"start" | "center" | "end"—sideOffset?number—arrow?booleanfalseanchorPoint?TooltipPoint—事件
update:open—@update:openopenChange—@openChange插槽
default() => VNodeChild#defaultTooltipContent
side?"top" | "bottom" | "left" | "right""top"align?"start" | "center" | "end""center"sideOffset?number(point ? 12 : 8)arrow?booleanfalseanchorPoint?TooltipPoint—插槽
default() => VNodeChild#defaultTooltipProvider
delay?numberinherited.value.delaycloseDelay?numberinherited.value.closeDelayskipDelay?numberprops.skipDelayDurationskipDelayDuration?number—插槽
default() => VNodeChild#default无障碍
为交互控件提供明确的无障碍名称。保留文档中的键盘路径、可见焦点与减少动态效果状态;自定义插槽应继续保留所替代部件的语义。
常见问题
- 如何配置 Tooltip?
- 通过 content、open、defaultOpen、delay、closeDelay、disabled、asLabel、followCursor、anchorRef、id、side、align、sideOffset、arrow、anchorPoint 配置 Tooltip;API 表列出其类型与默认值。
- 如何连接到应用状态?
- 监听 update:open、openChange,将组件连接到应用状态。
- 可以在服务端渲染吗?
- 可以在 Vue SSR 应用中正常渲染。服务端与客户端的初始 props 应保持一致;浏览器测量与交互资源在挂载后启动。
更新于
来源与许可 ↗MIT · 0.1.1