跳到主要内容

修复主题切换时颜色过渡延迟(WEB-1207)

版本: 0.8.0 · 类型: 🐛 Bug Fix

WEB-1207

问题

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/designglobals.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.tsx
  • packages/design-site/src/theme/Root.tsx

改动内容

  1. 新增并导出共享工具 suppressThemeTransition(apply)。首次调用时它会自行注入一次性的 <style>.pd-theme-switching * { transition: none !important; },幂等、全局仅一份),从而不依赖使用方 import globals.css——monorepo 内各 app(web4 / design-site)各有独立 CSS 入口,只有自包含的工具才能对所有消费方通用。
  2. suppressThemeTransition 在执行 apply(真正翻转主题 DOM 状态的回调)前给 <html>.pd-theme-switchingapply 后强制一次同步样式计算(getComputedStyle)让变量翻转在过渡禁用状态下提交,再于下一 requestAnimationFrame 移除该 class。主题切换变为瞬时,hover / selected 等交互过渡不受影响。
  3. DesignProvider 的主题 useEffect 改用 suppressThemeTransition 包裹 data-theme / .dark 翻转。
  4. design-site 的 Root.tsx MutationObserver 在检测到 data-theme 变化时,用 suppressThemeTransition(syncDarkClass).dark——observer 回调仍在浏览器 paint 之前触发,来得及在过渡禁用状态下提交变量翻转。
  5. 为该工具补充单测(跨帧的 class 生命周期、apply 仅调用一次、<style> 注入幂等)。