mirror of
https://github.com/Kong/insomnia.git
synced 2026-11-06 04:53:59 -05:00
## Background Toast add/remove animations run through the View Transition API. While such a transition is active, Chromium retargets hit-testing for the whole viewport to `<html>` - including the moment a newer transition skips the running one - so a click can arrive with `document.documentElement` as its target. react-aria's `useInteractOutside` reads such an event as a click outside an open modal and closes it. Reproduction: open Settings → General → Software Updates and click **Check** repeatedly. Every click fires toasts, every toast mutation starts a view transition, and a click landing in one of those windows closed the Settings modal itself. ## Changes - `packages/insomnia/src/ui/css/styles.css`: disable pointer events on the `::view-transition` overlay and exclude the root element from the transition, so clicks keep reaching real elements while a toast animates. Both rules are required: the overlay rule alone still leaves the captured root's contents unhittable ([spec rationale](https://drafts.csswg.org/css-view-transitions-1/#view-transition-stacking-layer)), and excluding the root alone still leaves the overlay swallowing the clicks. The same pair is documented for this scenario in [Keeping the page interactive while a View Transition is running](https://www.bram.us/2025/01/29/view-transitions-page-interactivity/) and [csswg-drafts#11596](https://github.com/w3c/csswg-drafts/issues/11596). - `packages/insomnia/src/ui/components/toast-notification.tsx`: drop `pointerdown`/`click` events that were retargeted to `<html>` while a view transition is active. Those clicks cannot be attributed to their real target (hit-testing was suppressed by the browser) and were being misread as clicks outside an open modal. Events that land on real elements are untouched. Registration is guarded with `typeof window !== 'undefined'` because this module is also evaluated in Node (dev server, prerender). - `packages/insomnia/src/ui/components/toast-notification.tsx`: remove the stale `[view-transition-name:toast]` utility, which the inline per-toast `view-transition-name` has always overridden. - `packages/insomnia/src/ui/css/styles.css`: remove the `::view-transition-new(toast)` / `::view-transition-old(toast)` slide rules and their keyframes. They selected a group named `toast`, which never existed because toasts need unique names (a duplicate `view-transition-name` aborts the whole transition), so they never applied. - `packages/insomnia/src/ui/components/check-for-updates-button.tsx`: the button was fully disabled in development mode, which made this bug impossible to reproduce manually. It now shows a toast instead ("Updates are disabled in development mode"). Production behaviour is unchanged. ## Notes - Measured with real (CDP/`sendInputEvent`) input against the real components in Electron 43.2.0 / Chromium 150.0.7871.129: without the change a click during a toast animation hits `<html>` and closes the modal; with it the button keeps receiving clicks (25/17/12 clicks handled for 60/90/130ms click intervals) and the modal stays open. - No regressions measured: clicks while no transition runs (20/20 handled), mask click dismissal, Escape dismissal, popover outside-click dismissal (also while a transition runs), and clicking a toast. - Residual: hit-testing still returns `<html>` for the fraction of a click that lands inside a transition window (~10% of samples under rage clicking) - that is compositor behaviour and cannot be opted out. Such clicks are now dropped instead of dismissing the modal, which means that one click does nothing. - `:root { view-transition-name: none }` applies to every view transition in the app; the rule is commented in place so it is revisited if transitions other than toasts are introduced. Related: https://github.com/Kong/insomnia/pull/10553