focus-trap-react: Doesn't seem to work in other documents

I appreciate the effort you have put into making the focus trap library work in iframes and child windows, but unfortunately it seems like maybe the React version is not prepared for this?

I’m using the FocusTrap like <FocusTrap active={element !== null} focusTrapOptions={{document}}>, where document is the document of the child window (derived from element.ownerDocument), but the focus trap still isn’t trapping focus. When the same component is used in the main document, it works just fine.

Do you know what could be the cause of the issue?

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 25 (15 by maintainers)

Commits related to this issue

Most upvoted comments

And there’s no way you can change your code to delay the inclusion of the focus trap component to when the document has stabilized? Like don’t render the trap until you have the document you need…

This… is impossible? Like, my component doesn’t know where it’s mounted until it’s been mounted.

That’s true. Then rendering with <FocusTrap> could cause the div to change, causing the ref to change, and I guess it could be a different document at that point, though that seems unlikely. Still, it wouldn’t be totally “clean” to assume it’s the same document.

Because this is kind of a big change to the way it’s currently working.

It’s not. It’s highly unlikely people are relying on when the document field is read from the options. If anything this fixes a bug, where the focus trap reads the options before they are ready.

I’ll give this some thought. It’s a significant change in terms of when the trap gets created. I’ll have to check focus-trap to see if creating the trap triggers any events for which you might expect a callback in one of the options, in which case, you wouldn’t get the callback at the same time anymore.

If that turns out to be a problem, then another option might be to promote the document option to a prop (instead of nesting it in focusTrapOptions where there’s no “notification” if it changes) and then re-create the trap if that prop changes. Then we could maintain existing behavior and only have changes affect changing the document.

So something like componentDidMount(), only call this.setupFocusTrap() if this.props.active is true, and then in componentDidUpdate(), check if (!prevProps.active && this.props.active) and call this.setupFocusTrap() (if it doesn’t already exist).