radix-ui / primitives

Radix Primitives is an open-source UI component library for building high-quality, accessible design systems and web apps. Maintained by @workos.
https://radix-ui.com/primitives
MIT License
15.8k stars 820 forks source link

Toast dismissal pauses on iframe focus #1362

Open jonathanharrell opened 2 years ago

jonathanharrell commented 2 years ago

Bug report

When Toasts are used in an application that has an embedded iframe, if the iframe receives focus, the Toast registers that as a window blur and automatic toast dismissal is paused. For apps that make heavy use of iframes, this is a problem since the toasts stick around for a long time.

Suggested solution

Either check to see if an iframe is focused and in that case, don't pause the toast timers, OR provide a prop that lets users choose whether they want a window blur to pause the toast timers are not.

Your environment

Software Name(s) Version
Radix Package(s) @radix-ui/react-toast 0.1.1
React n/a 17.0.2
Browser Chrome 100.0.4896.75
Operating System MacOS 12.0.1
benoitgrelard commented 2 years ago

Hi @jonathanharrell,

Just to clarify, do you mean that the Toast are rendered in a iframe inside the main app? Or do you mean that the Toast are rendered in the main app, and the main app has other content in iframes?

Thanks

jjenzz commented 2 years ago

@benoitgrelard either of those scenarios wouldn't work.

it seems the window focus/blur listeners need to be window.parent.addEventListener() with a check to see if the new window receiving focus is inside the current window:

if (event.target.parent !== event.currentTarget) { 
  /* pause */ 
}

unless you think that toasts in an iframe should pause when the iframe loses focus to its parent? if so, something like the check above is potentially all that is missing.

jonathanharrell commented 2 years ago

My particular use case was a Toast rendered in the main app getting paused when an iframe embedded in that app receives focus. But the other scenario also seems like a concern.

jonathanharrell commented 2 years ago

At the very least, onPause and onResume props could be useful to override the default behavior.

jjenzz commented 2 years ago

i think those props would be a good addition regardless to allow people to add progress bars to their toasts. i think that was a feature request elsewhere.

andy-hook commented 2 years ago

I did some investigation and cross-origin becomes an issue as we'd need access to contentWindow in order to bind focus / blur events.

The main issue is the inability to determine intent with window.blur / focus alone, for example window.focus will not fire if the window is blurred and we focus directly into a child iframe.



@jonathanharrell Can I ask what the architecture of your app looks like and how it makes use of iframes? Are they typically same origin?

jonathanharrell commented 2 years ago

Yes, my particular app uses iframes coming from the same origin.