Tooltip 工具提示
当用户悬停或聚焦某个元素时,展示提示性文本。
用法
import { Tooltip } from '@lenso/ui';此预览复用英文版适配,不代表中文源示例已完成本地实现。
"use client";
// Adapted from HeroUI v3.2.6 tooltip-basic (Apache-2.0).import { CircleInfo } from "@gravity-ui/icons";import * as stylex from "@stylexjs/stylex";import { Button, Tooltip } from "@lenso/ui";import { useId } from "react";
const styles = stylex.create({ row: { display: "flex", alignItems: "center", gap: 16 } });
export function TooltipBasic() { const textId = useId(); const informationId = useId(); return ( <Tooltip.Provider delay={0}> <div {...stylex.props(styles.row)}> <Tooltip> <Tooltip.Trigger aria-describedby={textId} render={<Button variant="secondary" />}> Hover me </Tooltip.Trigger> <Tooltip.Portal> <Tooltip.Positioner> <Tooltip.Popup id={textId}>This is a tooltip</Tooltip.Popup> </Tooltip.Positioner> </Tooltip.Portal> </Tooltip> <Tooltip> <Tooltip.Trigger aria-describedby={informationId} render={<Button isIconOnly aria-label="More information" variant="tertiary" />} > <CircleInfo /> </Tooltip.Trigger> <Tooltip.Portal> <Tooltip.Positioner> <Tooltip.Popup id={informationId}>More information</Tooltip.Popup> </Tooltip.Positioner> </Tooltip.Portal> </Tooltip> </div> </Tooltip.Provider> );}Local adaptation source above. Derived from HeroUI v3.2.6 source.
组件结构
import { Tooltip, Button } from '@lenso/ui';
export default () => ( <Tooltip> <Tooltip.Trigger> <Button>Hover for tooltip</Button> </Tooltip.Trigger> <Tooltip.Content> <Tooltip.Arrow /> 关于此元素的有用信息 </Tooltip.Content> </Tooltip>)示例
位置
此预览复用英文版适配,不代表中文源示例已完成本地实现。
"use client";
// Adapted from HeroUI v3.2.6 tooltip-placement (Apache-2.0).import { Button, Tooltip } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";import { useId } from "react";import { tokens } from "@lenso/tokens/tokens.stylex.const";
const styles = stylex.create({ grid: { display: "grid", gridTemplateColumns: "repeat(3, minmax(0, 1fr))", gap: 16 }, center: { display: "flex", alignItems: "center", justifyContent: "center" }, caption: { fontSize: 14, color: tokens.muted }, button: { width: "100%" },});
function Placement({ side, label }: { side: "top" | "left" | "right" | "bottom"; label: string }) { const id = useId(); return ( <Tooltip> <Tooltip.Trigger delay={0} aria-describedby={id} render={<Button variant="tertiary" xstyle={styles.button} />} > {label} </Tooltip.Trigger> <Tooltip.Portal> <Tooltip.Positioner side={side} sideOffset={7}> <Tooltip.Popup id={id}> <Tooltip.Arrow /> <p>{label} placement</p> </Tooltip.Popup> </Tooltip.Positioner> </Tooltip.Portal> </Tooltip> );}
export function TooltipPlacement() { return ( <div {...stylex.props(styles.grid)}> <div /> <Placement side="top" label="Top" /> <div /> <Placement side="left" label="Left" /> <div {...stylex.props(styles.center)}> <span {...stylex.props(styles.caption)}>Hover buttons</span> </div> <Placement side="right" label="Right" /> <div /> <Placement side="bottom" label="Bottom" /> <div /> </div> );}Local adaptation source above. Derived from HeroUI v3.2.6 source.
带箭头
此预览复用英文版适配,不代表中文源示例已完成本地实现。
"use client";
// Adapted from HeroUI v3.2.6 tooltip-with-arrow (Apache-2.0).import { Button, Tooltip } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";import { useId } from "react";
const styles = stylex.create({ row: { display: "flex", alignItems: "center", gap: 16 } });
export function TooltipWithArrow() { const arrowId = useId(); const offsetId = useId(); return ( <div {...stylex.props(styles.row)}> <Tooltip> <Tooltip.Trigger delay={0} aria-describedby={arrowId} render={<Button variant="secondary" />} > With Arrow </Tooltip.Trigger> <Tooltip.Portal> <Tooltip.Positioner sideOffset={7}> <Tooltip.Popup id={arrowId}> <Tooltip.Arrow /> <p>Tooltip with arrow indicator</p> </Tooltip.Popup> </Tooltip.Positioner> </Tooltip.Portal> </Tooltip> <Tooltip> <Tooltip.Trigger delay={0} aria-describedby={offsetId} render={<Button variant="primary" />} > Custom Offset </Tooltip.Trigger> <Tooltip.Portal> <Tooltip.Positioner sideOffset={12}> <Tooltip.Popup id={offsetId}> <Tooltip.Arrow /> <p>Custom offset from trigger</p> </Tooltip.Popup> </Tooltip.Positioner> </Tooltip.Portal> </Tooltip> </div> );}Local adaptation source above. Derived from HeroUI v3.2.6 source.
自定义触发
此预览复用英文版适配,不代表中文源示例已完成本地实现。
"use client";
// Adapted from HeroUI v3.2.6 tooltip-custom-trigger (Apache-2.0).import { CircleCheckFill, CircleQuestion } from "@gravity-ui/icons";import { Avatar, Chip, Tooltip } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";import { useId } from "react";import { tokens } from "@lenso/tokens/tokens.stylex.const";
const ping = stylex.keyframes({ "75%": { transform: "scale(2)", opacity: 0 }, "100%": { transform: "scale(2)", opacity: 0 },});const styles = stylex.create({ row: { display: "flex", alignItems: "center", gap: 24 }, profile: { display: "flex", flexDirection: "column", gap: 0, paddingBlock: 4 }, strong: { fontWeight: 600 }, email: { fontSize: 12, color: tokens.muted }, status: { display: "flex", alignItems: "center", gap: 6 }, dot: { position: "relative", display: "flex", width: 8, height: 8 }, pulse: { position: "absolute", display: "inline-flex", width: "100%", height: "100%", borderRadius: "50%", backgroundColor: tokens.success, opacity: 0.75, animationName: { default: ping, "@media (prefers-reduced-motion: reduce)": "none" }, animationDuration: "1s", animationTimingFunction: "cubic-bezier(0, 0, .2, 1)", animationIterationCount: "infinite", }, dotCenter: { position: "relative", display: "inline-flex", width: 8, height: 8, borderRadius: "50%", backgroundColor: tokens.success, }, iconBackground: { borderRadius: "50%", backgroundColor: tokens.accentSoft, padding: 8 }, icon: { color: tokens.accentSoftForeground }, help: { maxWidth: 320, paddingInline: 4, paddingBlock: 6 }, helpHeading: { marginBottom: 4, fontWeight: 600 }, helpText: { fontSize: 14, color: tokens.muted },});
export function TooltipCustomTrigger() { const avatarId = useId(); const statusId = useId(); const infoId = useId(); return ( <div {...stylex.props(styles.row)}> <Tooltip> <Tooltip.Trigger delay={0} aria-label="User avatar" aria-describedby={avatarId}> <Avatar size="sm"> <Avatar.Image alt="Jane Doe" src="https://img.heroui.chat/image/avatar?w=400&h=400&u=4" /> <Avatar.Fallback>JD</Avatar.Fallback> </Avatar> </Tooltip.Trigger> <Tooltip.Portal> <Tooltip.Positioner sideOffset={7}> <Tooltip.Popup id={avatarId}> <Tooltip.Arrow /> <div {...stylex.props(styles.profile)}> <p {...stylex.props(styles.strong)}>Jane Doe</p> <p {...stylex.props(styles.email)}>[email protected]</p> </div> </Tooltip.Popup> </Tooltip.Positioner> </Tooltip.Portal> </Tooltip> <Tooltip> <Tooltip.Trigger delay={0} aria-label="Status chip" aria-describedby={statusId}> <Chip color="success"> <CircleCheckFill width={12} /> <Chip.Label>Active</Chip.Label> </Chip> </Tooltip.Trigger> <Tooltip.Portal> <Tooltip.Positioner> <Tooltip.Popup id={statusId} xstyle={styles.status}> <span {...stylex.props(styles.dot)} aria-hidden="true"> <span {...stylex.props(styles.pulse)} /> <span {...stylex.props(styles.dotCenter)} /> </span> <p>Jane is currently online</p> </Tooltip.Popup> </Tooltip.Positioner> </Tooltip.Portal> </Tooltip> <Tooltip> <Tooltip.Trigger delay={0} aria-label="Info icon" aria-describedby={infoId}> <div {...stylex.props(styles.iconBackground)}> <CircleQuestion {...stylex.props(styles.icon)} /> </div> </Tooltip.Trigger> <Tooltip.Portal> <Tooltip.Positioner sideOffset={7}> <Tooltip.Popup id={infoId}> <Tooltip.Arrow /> <div {...stylex.props(styles.help)}> <p {...stylex.props(styles.helpHeading)}>Help Information</p> <p {...stylex.props(styles.helpText)}> This is a helpful tooltip with more detailed information about this feature. </p> </div> </Tooltip.Popup> </Tooltip.Positioner> </Tooltip.Portal> </Tooltip> </div> );}Local adaptation source above. Derived from HeroUI v3.2.6 source.
渲染函数
此预览复用英文版适配,不代表中文源示例已完成本地实现。
"use client";
// Adapted from HeroUI v3.2.6 tooltip-render-function (Apache-2.0).import { CircleInfo } from "@gravity-ui/icons";import { Button, Tooltip } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";import { useId } from "react";
const styles = stylex.create({ row: { display: "flex", alignItems: "center", gap: 16 } });
export function RenderFunction() { const textId = useId(); const informationId = useId(); return ( <div {...stylex.props(styles.row)}> <Tooltip> <Tooltip.Trigger delay={0} aria-describedby={textId} render={<Button variant="secondary" />} > Hover me </Tooltip.Trigger> <Tooltip.Portal> <Tooltip.Positioner> <Tooltip.Popup id={textId} render={(props) => <div {...props} data-custom="foo" />}> <p>This is a tooltip</p> </Tooltip.Popup> </Tooltip.Positioner> </Tooltip.Portal> </Tooltip> <Tooltip> <Tooltip.Trigger delay={0} aria-describedby={informationId} render={<Button isIconOnly aria-label="More information" variant="tertiary" />} > <CircleInfo /> </Tooltip.Trigger> <Tooltip.Portal> <Tooltip.Positioner> <Tooltip.Popup id={informationId} render={(props) => <div {...props} data-custom="foo" />} > <p>More information</p> </Tooltip.Popup> </Tooltip.Positioner> </Tooltip.Portal> </Tooltip> </div> );}Local adaptation source above. Derived from HeroUI v3.2.6 source.
自定义样式
Tailwind CSS
此预览复用英文版适配,不代表中文源示例已完成本地实现。
"use client";
// Adapted from HeroUI v3.2.6 tooltip-custom-styles (Apache-2.0).import { Button, Tooltip } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";import { useId } from "react";import { tokens } from "@lenso/tokens/tokens.stylex.const";
const styles = stylex.create({ popup: { borderRadius: tokens.radiusLg, borderWidth: 1, borderStyle: "solid", borderColor: "color-mix(in oklab, var(--border) 80%, transparent)", backgroundColor: tokens.surface, paddingInline: 10, paddingBlock: 4, fontSize: 12, color: tokens.foreground, boxShadow: "0 1px 2px 0 rgb(0 0 0 / 0.05)", },});
export function CustomStyles() { const id = useId(); return ( <Tooltip> <Tooltip.Trigger delay={0} aria-describedby={id} render={<Button variant="secondary" />}> Share link </Tooltip.Trigger> <Tooltip.Portal> <Tooltip.Positioner> <Tooltip.Popup id={id} xstyle={styles.popup}> <p>Copied to clipboard</p> </Tooltip.Popup> </Tooltip.Positioner> </Tooltip.Portal> </Tooltip> );}Local adaptation source above. Derived from HeroUI v3.2.6 source.
全局 CSS
若要自定义组件类,可使用 @layer components 指令。了解更多。
@layer components { .tooltip { @apply rounded-xl shadow-lg; }
.tooltip__trigger { @apply cursor-help; }}样式参考
HeroUI 遵循 BEM 方法论,确保组件变体与状态可复用且易于自定义。
全局延迟配置
你可以通过定义 CSS 变量,为应用中所有 Tooltip 设置默认的显示与隐藏延迟:
/* 在你的全局 CSS 文件中 */:root { --tooltip-delay: 1500ms; --tooltip-close-delay: 500ms;}
/* 也可以为浅色/深色主题设置不同的值 */.light, [data-theme="light"] { --tooltip-delay: 1200ms;}
.dark, [data-theme="dark"] { --tooltip-close-delay: 300ms;}值支持 ms、s 等 CSS 时间单位。在单个 Tooltip 上指定 delay 或 closeDelay 时,会覆盖这些全局设置。
CSS 类
Tooltip 使用以下 CSS 类(查看源码样式):
基础类 [!toc]
.tooltip- 带动画的基础 Tooltip 样式.tooltip__trigger- 触发元素样式
交互状态
组件支持以下动画相关状态:
- 进入:
[data-entering]— Tooltip 出现过程中应用 - 离开:
[data-exiting]— Tooltip 消失过程中应用 - 位置:
[data-placement="*"]— 根据 Tooltip 位置应用
API 参考
Tooltip
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
children | React.ReactNode | - | 触发元素与内容 |
delay | number | 1500 或 CSS 变量 | 显示 Tooltip 前的延迟(毫秒);可通过 --tooltip-delay CSS 变量全局配置 |
closeDelay | number | 500 或 CSS 变量 | 隐藏 Tooltip 前的延迟(毫秒);可通过 --tooltip-close-delay CSS 变量全局配置 |
trigger | "hover" | "focus" | "hover" | Tooltip 的触发方式 |
isDisabled | boolean | false | 是否禁用 Tooltip |
shouldSkipAnimation | boolean | false | 在多个 Tooltip 之间快速切换时,是否跳过进入与退出动画 |
Tooltip.Content
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
children | React.ReactNode | - | 在 Tooltip 中展示的内容 |
showArrow | boolean | false | 是否显示箭头指示器 |
offset | number | 3(带箭头时为 7) | 与触发元素的距离 |
placement | "top" | "bottom" | "left" | "right" (及变体) | "top" | Tooltip 的位置 |
className | string | - | 额外的 CSS 类名 |
render | DOMRenderFunction<keyof React.JSX.IntrinsicElements, TooltipRenderProps> | - | 通过自定义渲染函数覆盖默认的 DOM 元素。 |
Tooltip.Trigger
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
children | React.ReactNode | - | 触发 Tooltip 的元素 |
className | string | - | 额外的 CSS 类名 |
Tooltip.Arrow
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
children | React.ReactNode | - | 自定义箭头元素 |
className | string | - | 额外的 CSS 类名 |
render | DOMRenderFunction<keyof React.JSX.IntrinsicElements, OverlayArrowRenderProps> | - | 通过自定义渲染函数覆盖默认的 DOM 元素。 |