shadcn-svelte Tooltip 组件完全指南:从 Provider 到 Content 的源码级实战
【免费下载链接】shadcn-svelteshadcn/ui, but for Svelte. ✨项目地址: https://gitcode.com/GitHub_Trending/sh/shadcn-svelte
Tooltip(提示气泡)是 shadcn-svelte 中基于 bits-ui 封装的高频交互组件,用于在元素获得键盘焦点或鼠标悬停时展示补充信息。本文以 Tooltip 官方文档 为主线,结合 组件源码 与 仓库内真实示例,完整讲解安装方式、Provider 架构、Root/Trigger/Content 的用法、嵌套 Provider 场景以及 2025-12 颜色更新,帮助你直接在项目中落地一套无障碍、可复制的 Tooltip 方案。
组件架构一览
shadcn-svelte 的 Tooltip 由 5 个可组合子组件构成,全部通过 index.ts 统一导出为命名空间形式:
| 子组件 | 底层实现 | 职责 |
|---|---|---|
Tooltip.Root | tooltip.svelte | 状态容器,绑定open开关 |
Tooltip.Trigger | tooltip-trigger.svelte | 触发元素,支持键盘聚焦 |
Tooltip.Content | tooltip-content.svelte | 气泡内容与箭头,默认渲染在 Portal 中 |
Tooltip.Provider | tooltip-provider.svelte | 全局协调器,控制同一时刻只打开一个 Tooltip |
Tooltip.Portal | tooltip-portal.svelte | 将气泡渲染到 body 层级,避免父级overflow/z-index干扰 |
从 index.ts 可以看到,除了命名空间别名,还同时导出了TooltipContent、TooltipTrigger等扁平命名,两种引用方式等价。所有组件都直接透传 bits-ui 的RootProps/ContentProps/ProviderProps,因此 bits-ui Tooltip 的全部配置能力都保留给了调用方。
安装
与 shadcn-svelte 其他组件一致,Tooltip 提供 CLI 与手动两种安装路径,二者等价。
CLI 一键安装
在项目根目录执行:
npx shadcn-svelte@latest add tooltipCLI 会自动解析依赖、写入组件文件并处理样式与注册表配置。对于使用 pnpm 的项目,可替换为pnpm dlx shadcn-svelte@latest add tooltip,npm 用户则使用npx。
手动安装
- 安装运行时依赖
bits-ui:
npm install bits-ui -D将仓库
docs/src/lib/registry/ui/tooltip/目录下的 6 个文件(index.ts、tooltip.svelte、tooltip-trigger.svelte、tooltip-content.svelte、tooltip-provider.svelte、tooltip-portal.svelte)复制到你的$lib/components/ui/tooltip/目录。确保项目中的
cn()工具函数(一般位于$lib/utils.js)与 Tailwind 配置可正常解析组件内部使用的cn()与data-slot类。
使用:三步搭好全局 Tooltip
第一步:在根布局挂载 Provider
Tooltip.Provider是协调中心,官方文档明确要求它只放置一次,并且包裹所有可能包含 Tooltip 的内容,以保证在 Provider 作用域内同一时刻只有一个 Tooltip 处于打开状态。
在src/routes/+layout.svelte中引入:
<script lang="ts"> import * as Tooltip from "$lib/components/ui/tooltip/index.js"; let { children } = $props(); </script>然后在模板中包裹插槽:
<Tooltip.Provider> {@render children()} </Tooltip.Provider>从 tooltip-provider.svelte 源码可见,Provider 的默认参数为delayDuration = 0,即悬停后立即显示,不附加延迟;...restProps会把 bits-ui Provider 的其他配置(如skipDelayDuration、disableHoverableContent等)透传下去。
第二步:组合 Root / Trigger / Content
在任意页面或组件中使用:
<script lang="ts"> import * as Tooltip from "$lib/components/ui/tooltip/index.js"; </script> <Tooltip.Root> <Tooltip.Trigger>Hover</Tooltip.Trigger> <Tooltip.Content> <p>Add to library</p> </Tooltip.Content> </Tooltip.Root>这是仓库 tooltip-demo 演示的官方标准用法。结合源码补充说明:
- Root:见 tooltip.svelte,声明
open = $bindable(false),因此你可以通过bind:open受控管理 Tooltip 的开合状态,例如配合快捷键或按钮切换显示。 - Trigger:见 tooltip-trigger.svelte,透传 bits-ui Trigger,自动获得键盘聚焦(Tab 聚焦后按 Enter/Space)与鼠标悬停两种触发方式,并带有
data-slot="tooltip-trigger"标识,方便样式钩子。Trigger 本身不产生额外 DOM 包装,直接渲染在触发元素上。 - Content:见 tooltip-content.svelte,默认渲染在
TooltipPortal中,默认side = "top"、sideOffset = 0,并内置了可选的箭头(TooltipPrimitive.Arrow)。它还支持arrowClasses与portalProps两个额外属性,分别用于定制箭头样式和 Portal 行为。
第三步:结合按钮组件增强样式
仓库演示中常将 Trigger 与按钮变体组合,例如 tooltip-demo.svelte:
<Tooltip.Provider> <Tooltip.Root> <Tooltip.Trigger class={buttonVariants({ variant: "outline" })}>Hover</Tooltip.Trigger> <Tooltip.Content> <p>Add to library</p> </Tooltip.Content> </Tooltip.Root> </Tooltip.Provider>buttonVariants由$lib/registry/ui/button/index.js(或你项目中的$lib/components/ui/button/index.js)导出,直接复用按钮视觉体系,让触发元素与页面其他按钮风格统一。
进阶技巧:嵌套 Provider 与分组配置
官方文档提供了一个高频场景:嵌套 Provider。Tooltip 遵循"最近祖先 Provider"原则——当页面同时存在外层与内层 Provider 时,内层 Tooltip 使用距离最近的 Provider 配置。这非常适合在特定区域覆盖全局设置:
<Tooltip.Provider delayDuration={0}> <!-- Tooltips here will open instantly --> </Tooltip.Provider>外层 Provider 若设置了较长的delayDuration(例如 700ms)作为全站统一延迟,内层嵌套delayDuration={0}的 Provider 即可让该区域 Tooltip 即时弹出,典型用于工具栏、图标按钮密集区域。仓库示例 tooltip-basic.svelte 等大量示例也印证了Provider包裹Root的标准层级结构。
实战扩展:仓库示例中的边界场景
禁用状态下仍可触发 Tooltip
原生 disabled 按钮不会触发鼠标事件,Tooltip 因而失效。仓库 tooltip-disabled.svelte 给出了官方解法:用Tooltip.Trigger的childsnippet 包一层span,把触发行为交给外层 span:
<Tooltip.Root> <Tooltip.Trigger> {#snippet child({ props })} <span class="inline-block w-fit" {...props}> <Button variant="outline" disabled>Disabled</Button> </span> {/snippet} </Tooltip.Trigger> <Tooltip.Content> <p>This feature is currently unavailable</p> </Tooltip.Content> </Tooltip.Root>childsnippet 让 Trigger 把事件与无障碍属性(aria-describedby等)附着到包裹 span 上,从而在禁用按钮场景下也能弹出说明气泡。同类技巧也见于 tooltip-on-link.svelte、tooltip-with-icon.svelte 等示例。
控制气泡方位
Tooltip.Content支持 bits-ui 的side属性,默认top。仓库 tooltip-sides.svelte 用#each遍历四种方位验证其可用性:
{#each ["top", "right", "bottom", "left"] as const as side (side)} <Tooltip.Root> <Tooltip.Trigger> {#snippet child({ props })} <Button variant="outline" class="w-fit capitalize" {...props}>{side}</Button> {/snippet} </Tooltip.Trigger> <Tooltip.Content {side}> <p>Add to library</p> </Tooltip.Content> </Tooltip.Root> {/each}此外sideOffset(默认 0)用于调整气泡与触发元素的间距;当空间不足时,bits-ui 的浮层逻辑会自动翻转方位,Content 源码中的origin-(--bits-tooltip-content-transform-origin)类即配合翻转做入场动画。
格式化内容与键盘提示
Tooltip 内容不止于纯文本:仓库还提供了 tooltip-formatted.svelte(富文本/多行排版)与 tooltip-with-keyboard.svelte(在气泡内展示<kbd>快捷键)等示例,均可作为扩展样式参考。仓库其余模块(如 Sidebar 的 sidebar-menu-button.svelte、Bubble 的 bubble-tooltip.svelte)也在内部复用了 Tooltip 组件,可作为大型组件组合使用的样板。
2025-12 样式更新:Foreground/Background 配色方案
官方文档记录了 2025-12 的一次重要样式变更:Tooltip 颜色由bg-primary text-primary-foreground改为bg-foreground text-background,即气泡背景使用前景色、文字使用背景色。这一调整在 tooltip-content.svelte 的源码中已生效:
class={cn( "cn-tooltip-content z-50 w-fit max-w-xs origin-(--bits-tooltip-content-transform-origin) bg-foreground text-background", className )}箭头部分同样跟随新方案,见同文件 tooltip-content.svelte 的cn-tooltip-arrow bg-foreground fill-foreground。
如果你在旧版本或自定义主题中仍使用bg-primary text-primary-foreground,请替换为bg-foreground text-background,保证与新版主题体系一致。同时注意:
- Content 的类前缀为
cn-tooltip-content、cn-tooltip-arrow,可通过这些稳定类名在全局 CSS 中追加自定义样式; - 宽度约束为
w-fit max-w-xs,超出即换行,避免超长内容撑破布局; - 默认
z-50层级,配合 Portal 渲染可覆盖绝大多数页面层级。
无障碍与可访问性要点
基于 bits-ui 底层实现,Tooltip 开箱即用具备以下无障碍特性(可从 Trigger/Content 透传属性推断):
- 键盘可触发:Tab 聚焦 Trigger 后,按 Enter/Space 即可显示气泡,无需鼠标;
- ARIA 关联:Content 自动挂载
role="tooltip"并通过aria-describedby与 Trigger 建立关联,屏幕阅读器可朗读气泡内容; - 焦点与悬停双路径:鼠标悬停与键盘聚焦共享同一套开合状态,均由 Root 的
open绑定统一管理。
如需完全受控,可在 Root 上使用bind:open,将开合状态提升到父组件,便于实现"首次访问引导""条件显示"等业务逻辑。
小结
- 安装:
npx shadcn-svelte@latest add tooltip或手动复制 tooltip 目录 并安装bits-ui; - 架构:Provider(全局唯一)→ Root → Trigger → Content,Content 默认经 Portal 渲染并带箭头;
- 关键配置:Provider 的
delayDuration(默认 0)、Content 的side(默认 top)与sideOffset(默认 0)、Root 的bind:open; - 禁用态处理:使用 Trigger 的
childsnippet 包裹 span,参考 tooltip-disabled.svelte; - 配色更新:统一采用
bg-foreground text-background,勿再使用旧版bg-primary text-primary-foreground。
按以上步骤即可在 shadcn-svelte 项目中快速获得一套键盘友好、样式统一、可深度定制的 Tooltip 体系;需要查看更多边界示例时,可直接浏览仓库的 create/tooltip 示例集。
【免费下载链接】shadcn-svelteshadcn/ui, but for Svelte. ✨项目地址: https://gitcode.com/GitHub_Trending/sh/shadcn-svelte
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考