fix(toast): auto-dismiss toasts when the app window is unfocused - #4063
fix(toast): auto-dismiss toasts when the app window is unfocused#4063adamleithp wants to merge 2 commits into
Conversation
base-ui pauses a toast's auto-dismiss timer whenever the window isn't OS-focused, not only while it's hovered. On the desktop app the window is frequently not frontmost, so a toast (e.g. "Task archived") would hang on screen until closed by hand. Back base-ui's timer with a blur-only fallback in the shared toast wrapper: once a toast's time is up, if the window is unfocused, dismiss it. When the window is focused we do nothing and leave base-ui's own timer and its hover-to-pause behavior in charge. Generated-By: PostHog Code Task-Id: 48d0d198-f58f-46a2-be36-36aeb6517a93
|
Merging to
After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here |
|
React Doctor found no issues in the changed files. 🎉 Reviewed by React Doctor for commit |
Prompt To Fix All With AI### Issue 1
packages/ui/src/primitives/toast.tsx:67-71
**One-shot focus check misses later blur**
When a toast is hover-paused while focused at the fallback deadline and the window loses focus afterward, this callback has already exited permanently and base-ui pauses its remaining timer, causing the finite toast to remain visible until focus returns.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (1): Last reviewed commit: "fix(toast): auto-dismiss toasts when the..." | Re-trigger Greptile |
| setTimeout(() => { | ||
| if (!document.hasFocus()) { | ||
| quillToast.dismiss(quillId); | ||
| } | ||
| }, dismissAfter); |
There was a problem hiding this comment.
One-shot focus check misses later blur
When a toast is hover-paused while focused at the fallback deadline and the window loses focus afterward, this callback has already exited permanently and base-ui pauses its remaining timer, causing the finite toast to remain visible until focus returns.
Knowledge Base Used: @posthog/ui shared UI package
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/ui/src/primitives/toast.tsx
Line: 67-71
Comment:
**One-shot focus check misses later blur**
When a toast is hover-paused while focused at the fallback deadline and the window loses focus afterward, this callback has already exited permanently and base-ui pauses its remaining timer, causing the finite toast to remain visible until focus returns.
**Knowledge Base Used:** [`@posthog/ui` shared UI package](https://app.greptile.com/posthog-org-19734/-/custom-context/knowledge-base/posthog/code/-/docs/ui-package.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.The one-shot focus check gave up permanently if the window was focused at the fallback deadline (e.g. hover-paused). If the window then lost focus while the toast was still up, base-ui re-paused its timer and the toast hung until focus returned. Now, when focused at the deadline, arm a one-time window blur listener that dismisses on the next blur, cleaned up via the toast's onClose so nothing is left pending once it closes normally. Generated-By: PostHog Code Task-Id: 48d0d198-f58f-46a2-be36-36aeb6517a93
Problem
Toasts in the desktop app don't reliably auto-dismiss — the "Task archived" toast in particular hangs on screen until you close it by hand.
Root cause: the toast primitive wraps quill, which wraps base-ui's Toast. base-ui pauses a toast's auto-dismiss timer whenever the window isn't OS-focused (
hovering || focused || !isWindowFocused), not only while it's hovered. On a desktop app the window is frequently not the frontmost OS window, so the timer stays paused and the toast never expires. This affects every toast; archive is just where it's most visible, since you often move to another app right after archiving.Changes
Added a blur-only fallback in the shared toast wrapper (
packages/ui/src/primitives/toast.tsx): once a toast's time is up, if the window is unfocused, dismiss it. When the window is focused we do nothing and leave base-ui's own timer — and its hover-to-pause — in charge. Loading toasts and never-expiring (Infinity) toasts like the offline banner are left untouched.How did you test this?
vitest run src/primitives/toast.test.tsinpackages/ui— 17 pass, including 4 new cases covering: dismissal when unfocused (explicit duration and provider default), no dismissal when focused, and no dismissal for loading/Infinity toasts. Also ran biome check and tsc on the changed files (clean).Automatic notifications
Created with PostHog from a Slack thread