react-spectrum
react-spectrum copied to clipboard
<FocusScope contain/> doesn't work when rendered into an iframe
๐ Bug Report
When rendering something containing <FocusScope contain/>
into an iframe, FocusScope
has trouble detecting the newly-focused element and goes into an infinite focusing loop.
Here's a repro: https://codesandbox.io/s/react-aria-focusscope-in-iframe-0e6fkj?file=/src/App.tsx
You can focus on one input in the iframe, and as long as you focus on another input, FocusScope
will keep switching focus between the two.
The issue seems to be that in FocusScope.tsx
, onBlur
, it is checking if the newly-focused element is within the focus scope, and if not, returns the focus to the previously-focused node. Unfortunately it is assuming that document.activeElement
is the newly-focused element instead of using e.relatedTarget
, and document
refers to the parent frame and not the child frame, so it incorrectly tries to restore focus to the previously-focused input.
๐ค Expected Behavior
<FocusScope/>
continues working in an iframe.
๐ฏ Current Behavior
<FocusScope/>
cannot detect focused element across iframes.
๐ Possible Solution
It's possible here to look for activeElement in all the iframes until you find one, instead of directly relying on document.activeElement
. But then, I'm not sure if this is even a use case that react-aria is trying to allow ๐
I see many direct references to document
in the react-aria code, so they'll all probably break in some way when used across iframes.
๐ฆ Context
In Plasmic, we're allowing users to register React components that we then use to render in another iframe. This happens when those registered components use <FocusScope contain/>
.
๐ป Code Sample
https://codesandbox.io/s/react-aria-focusscope-in-iframe-0e6fkj?file=/src/App.tsx
๐ Your Environment
Software | Version(s) |
---|---|
@react-aria/focus | 3.6.1 |
๐งข Your Company/Team
Plasmic
Thanks for the sandbox, definitely not ideal. I forget exactly why I made this change, perhaps we could use e.relatedTarget instead of document.activeElement
Perhaps we can use the ownerDocument containing the FocusScope instead
I have a potential solution for this and would like to submit a RFC @LFDanLu
Sounds good, thanks! I'll bring it to the teams attention.
This appears to have been fixed, I can't reproduce with latest https://codesandbox.io/p/sandbox/react-aria-focusscope-in-iframe-forked-ds3vwm Thanks @slye-stripe, I'm guessing one of your PRs fixed it!