跳到主要内容

悬停中的 Toast 栈清空后恢复自动消失(WEB-1537)

版本: 0.10.0 · 类型: 🐛 Bug 修复

WEB-1537 · 来源问题:FM-1582

问题​

鼠标停在 Toast 堆上时,自动消失计时会暂停。如果此时关闭最后一条可见 Toast,之后新出现的有限时长 Toast 可能一直停留在页面上,并继续使用悬停展开态布局,直到页面刷新。

根因​

计时暂停保存在全局 toastManager.paused 状态中,但恢复完全依赖 Toaster 宿主的 mouseleave 事件。关闭最后一条可见 Toast 后,宿主 <ol> 会从 DOM 卸载;浏览器不会为已经移除的节点补发 mouseleave,因此 manager 一直保持暂停,后续 Toast 只登记定时器而不会启动。

堆叠展开态还单独保存在 Toaster 内,虽然它与暂停态由同一组 mouseenter / mouseleave 事件驱动,但两份状态会一起残留。

改动文件​

  • packages/design/src/components/Toast/toast-manager.ts
  • packages/design/src/components/Toast/Toaster.tsx
  • packages/design/src/components/Toast/__tests__/Toast.autoDismiss.test.tsx

改动内容​

  1. 暴露 toastManager.isPaused(),并在 pauseAll() / resumeAll() 改变暂停态后通知订阅方。
  2. dismiss() 将 Toast 标记为不可见后,若已无可见记录则立即调用 resumeAll()。该操作早于退场动画记录的真正移除,因此动画窗口内创建的新 Toast 也会正常启动计时。
  3. 删除 Toaster 本地的 expanded state,改为通过 useSyncExternalStore 读取 manager 的暂停快照,让计时暂停与堆叠布局共享单一事实源。
  4. 新增 5 条回归测试,覆盖普通自动消失、悬停暂停/恢复、悬停中关闭最后一条、退场动画期间创建下一条,以及恢复折叠堆叠布局。

影响范围​

悬停期间清空 Toast 栈后,新 Toast 会按配置时长正常自动消失。既有的悬停暂停、移开后续跑计时行为保持不变。本次没有公开 API 或视觉规范变化。