修复主题切换时颜色过渡延迟(WEB-1207)
版本: 0.8.0 · 类型: 🐛 Bug Fix
问题
Tree item 的基础样式带 transition-colors——本意是让 hover / selected 的背景色平滑淡入淡出。但 light / dark 主题切换会一次性翻转整套 CSS 变量(dark 取值同时绑定在 .dark 与 [data-theme='dark'] 两个选择器上)。带过渡的元素分不清颜色变化来自 :hover 还是主题切换,因此变量一翻转,transition-colors 就会把新旧颜色在 150ms 内做插值。结果是 Tree 行的背景 / 边框在 light↔dark 切换时"慢慢过渡"——即所谓的"颜色切换延迟"。又因为 title 文字 / icon 颜色没有过渡(瞬时切换),行内还会显得不同步。
问题还有第二层:主题切换点不止一个。DesignProvider 自己 set data-theme + toggle .dark;而 design-site(Docusaurus)走的是 Docusaurus 自带切换(同步改 data-theme),再由 Root.tsx 里的 MutationObserver 事后补 .dark——完全不经过 DesignProvider。且 design-site 与 web4 都不 import @plaud/design 的 globals.css。因此修复必须做成一个共享、自包含的工具,让各切换点各自接入,而不是塞进 DesignProvider 内部。
改动文件
packages/design/src/utils/theme-transition.ts(新增)packages/design/src/utils/__tests__/theme-transition.test.ts(新增)packages/design/src/utils/index.ts/packages/design/src/index.ts(导出)packages/design/src/provider/DesignProvider.tsxpackages/design-site/src/theme/Root.tsx
改动内容
- 新增并导出共享工具
suppressThemeTransition(apply)。首次调用时它会自行注入一次性的<style>(.pd-theme-switching * { transition: none !important; },幂等、全局仅一份),从而不依赖使用方 importglobals.css——monorepo 内各 app(web4 / design-site)各有独立 CSS 入口,只有自包含的工具才能对所有消费方通用。 suppressThemeTransition在执行apply(真正翻转主题 DOM 状态的回调)前给<html>加.pd-theme-switching,apply后强制一次同步样式计算(getComputedStyle)让变量翻转在过渡禁用状态下提交,再于下一requestAnimationFrame移除该 class。主题切换变为瞬时,hover / selected 等交互过渡不受影响。DesignProvider的主题useEffect改用suppressThemeTransition包裹data-theme/.dark翻转。- design-site 的
Root.tsxMutationObserver在检测到data-theme变化时,用suppressThemeTransition(syncDarkClass)补.dark——observer 回调仍在浏览器 paint 之前触发,来得及在过渡禁用状态下提交变量翻转。 - 为该工具补充单测(跨帧的 class 生命周期、
apply仅调用一次、<style>注入幂等)。