很多前端项目的交互问题,不是“做不出来”,而是“做出来以后越来越难维护”。
我这次重构博客时,最大的体感不是样式变好看了,而是一个更底层的变化:把交互基础设施从“组件里手搓”迁移到“可复用 primitives”之后,功能迭代速度和稳定性同时上来了。
一句话结论先放这:
问题不在你会不会写动画,而在你有没有把可访问性、焦点管理、状态反馈这些“地基能力”交给专业工具层。
这篇文章复盘我本次引入 Base UI(headless primitives)并升级 Gallery 交互的完整过程:为什么做、怎么做、踩了什么坑、最后拿到了什么。
以前我的 Gallery Lightbox 是能用的:能打开、能切图、能关闭。
但当需求一增加(比如复制反馈、tooltip 提示、缩放、拖拽、键盘快捷键),问题就冒头了:
这类代码最危险的地方是:短期看起来灵活,长期一定退化成“谁都不敢动”。
硬件同学很熟这个味道——就像你用飞线临时救板子,第一次有成就感,第三次开始怀疑人生。
我这次的判断标准很明确:
Base UI 刚好满足这三点。
它不是“给你一套外观”,而是“给你一套行为引擎”。
这也是我最看重的点:把不该重复发明的轮子,移出业务组件。
反模式:Dialog 已经在管弹层,但我还在业务代码里手动 document.body.style.overflow = 'hidden'。
结果?某些关闭路径下 overflow 残留,页面直接不能滚动。
改法很简单但很关键:
这就是“机制问题”而不是“某行代码写错”。
Tooltip + Toast + Provider先搭基础设施,再改业务组件。
我加了统一的 AppProviders,把 Theme / Tooltip / Toast 放在同一层:
// components/AppProviders.tsx
<ThemeProvider>
<Tooltip.Provider>
<Toast.Provider toastManager={appToastManager}>
{children}
<AppToastViewport />
</Toast.Provider>
</Tooltip.Provider>
</ThemeProvider>然后做一个轻量通知封装:
// lib/toast.ts
export const appToastManager = Toast.createToastManager()
export function notifySuccess(title: string, description: string) {
appToastManager.add({ title, description, type: 'success' })
}收益:复制链接、代码复制、下载反馈全部讲同一种“交互语言”。
核心替换:用 Dialog.Root / Portal / Backdrop / Popup / Close 管理弹层。
<Dialog.Root open={open} onOpenChange={setOpen}>
<Dialog.Portal>
<Dialog.Backdrop />
<Dialog.Popup>{/* image + controls */}</Dialog.Popup>
</Dialog.Portal>
</Dialog.Root>这一步把焦点管理、Escape 关闭、语义结构都拉回“标准轨道”。
这次不是只重构架构,我还补了几个用户真的会用到的交互:
+/-/0);zoom > 1 时支持按住拖拽平移;100%,避免状态污染。关键逻辑是这段:
style={{
transform: `translate(${pan.x}px, ${pan.y}px) scale(${zoom})`,
transformOrigin: `${zoomOrigin.x}% ${zoomOrigin.y}%`,
}}一句人话解释:缩放中心跟着你的鼠标点走,平移只在你按住拖拽时发生。
我用三个维度评估:
| 维度 | 改造前 | 改造后 |
|---|---|---|
| 交互一致性 | 各组件自定义反馈 | Tooltip/Toast 全局统一 |
| 可访问性与语义(A11y) | 依赖手工补 | Dialog/Tooltip 提供稳定底座 |
| 维护复杂度(认知负担) | 逻辑散落在业务组件 | 抽到 Provider + primitives,可复用 |
性能层面也没有引入重成本:
transform,浏览器合成层友好;如果你也在“想 modernize 一把,但怕改炸”,建议按这个顺序:
这次改造让我再次确认一件事:
现代化 UI 的关键,不是“更酷的动画”,而是“更可靠的交互系统”。
界面炫不炫,三天就习惯了; 但一个“顺手、不出戏、不会突然失控”的交互系统,会让你和用户都长期受益。