Skip to content

fix(toast): auto-dismiss toasts when the app window is unfocused - #4063

Open
adamleithp wants to merge 2 commits into
mainfrom
posthog-code/toast-auto-dismiss-when-window-unfocused
Open

fix(toast): auto-dismiss toasts when the app window is unfocused#4063
adamleithp wants to merge 2 commits into
mainfrom
posthog-code/toast-auto-dismiss-when-window-unfocused

Conversation

@adamleithp

Copy link
Copy Markdown
Contributor

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.ts in packages/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

  • Publish to changelog?
  • Alert Sales and Marketing teams?

Created with PostHog from a Slack thread

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
@trunk-io

trunk-io Bot commented Aug 1, 2026

Copy link
Copy Markdown

Merging to main in this repository is managed by Trunk.

  • To merge this pull request, check the box to the left or comment /trunk merge below.

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

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

React Doctor found no issues in the changed files. 🎉

Reviewed by React Doctor for commit 32e693e.

@adamleithp
adamleithp marked this pull request as ready for review August 1, 2026 08:14
@greptile-apps

greptile-apps Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor
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

Comment thread packages/ui/src/primitives/toast.tsx Outdated
Comment on lines +67 to +71
setTimeout(() => {
if (!document.hasFocus()) {
quillToast.dismiss(quillId);
}
}, dismissAfter);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant