作者:Dominik
- #1: Designing Design Systems
- #2: Tooltip Components Should Not Exist
- #3: Building Type-Safe Compound Components
我必须承认:网页应用中糟糕的工具提示是我最讨厌的事情之一。公平地说,工具提示确实很容易设计失误。需要考虑的因素很多:
- 可访问性
- 键盘交互性
- 所有用户体验一致性
- 避免隐藏关键信息
多年来,我见过许多设计系统试图为用户提供<Tooltip>组件,但在我看来它们有个共同点——用户永远不会按预期使用。从API设计角度看,这很可能意味着<Tooltip>组件作为抽象层过于底层,这也引出了我今天的犀利观点🌶:
我并非主张取消工具提示功能本身。当应用得当——无论对你的具体场景而言"得当"意味着什么——它们仍是宝贵的辅助工具。当然,教育或许能解决问题,但坦白说:极少有人会阅读文档,而AI只会复现它已见过的内容,因此很可能放大我们代码库中现有的反模式。
在探讨替代方案之前,让我们先剖析错误使用工具提示可能引发的潜在问题。
键盘交互性
这一点理应不言自明:我们应当为所有人构建网页应用,这意味着必须意识到并非所有用户都会使用鼠标。然而我经常遇到这样的实现方式——当触发提示的元素本身不可交互时,却仅在鼠标悬停时显示工具提示。
以广受欢迎的组件库Material UI为例,其文档中的基础工具提示示例如下:
<Tooltip title="Delete">
<IconButton>
<DeleteIcon />
</IconButton>
</Tooltip>
这很简单且有效,但如果我们只在图标周围添加<Tooltip>,或者在Badge等其他非交互元素周围添加,会发生什么情况:
<Tooltip title="Home">
<IconHome />
</Tooltip>
<Tooltip title="Unread Mails">
<Badge badgeContent={4} color="primary">
<IconMail color="action" />
</Badge>
</Tooltip>
没错——悬停时提示框仍会显示,但焦点状态下不会出现,因为按Tab键会直接跳过它。该元素不支持键盘交互,因此永远不会获得焦点,这意味着仅使用键盘导航时提示框永远不会出现。
此外,这种方案无法实现类型安全,因为我们无法控制传递给<Tooltip>组件的子元素类型。React Aria 的方案稍优,它会直接隐藏非交互元素的提示框,便于主要使用鼠标的开发者识别。解决方案是将自定义触发器包裹在 <Focusable> 组件中。虽然这比其他方案好得多,但仍存在其他问题,具体而言:
对所有用户而言,最小化意外
只要某个元素能添加<Tooltip>,总会有人尝试。我见过最离奇的提示框位置——比如出现在句子中间的某个文字上,却没有任何提示说明背后藏着附加信息。
但我也见过相反的情况。看到一个仅由无法理解的图标组成的按钮,却完全不知道点击后会发生什么,这让我极其恼火。
当开发者和设计师团队规模达到临界点时,应用程序中必然会出现这类不一致现象。
既然独立的<Tooltip>组件并非理想方案,设计系统还能采用哪些方法实现工具提示功能?我的观点是:
过去我见过效果特别好的做法包括:
- 交互组件如
<Button>或<Link>可添加可选的title属性。 这让我们能根据需要展示额外信息。交互元素通常在界面中很容易被发现,通过键盘Tab键也能定位到。 <IconButton>组件强制要求title属性。此举既能向用户解释图标含义,又为按钮提供符合无障碍标准的标注方式。- 引入额外的
<InfoIcon>组件,用于渲染信息图标/问号图标 + 工具提示。 - 这既能引导用户获取补充信息,又能确保该组件内部可获得焦点。
- 创建组件以提供文本补充说明。
- 该组件需通过视觉标识(如虚线下划线)与普通文本区分,并支持键盘交互操作。
我确信可能还有其他遗漏之处,但若真有遗漏,添加另一个模式组件也比让所有人访问底层的<Tooltip>组件更可取。别误会,灵活性在许多场景下确实很棒,比如布局设计,但对工具提示而言,提供一致的用户体验和包容性远比灵活重要得多,因此限制反而更好。
限制反而能激发创造力——当屏幕空间不足时,若不能简单地将信息塞进工具提示框,或许反而能促使我们从根本上重新思考设计方案。
因此,若您正在为组织构建设计系统,请务必克制在公共接口中添加<Tooltip>组件的冲动。