-
Notifications
You must be signed in to change notification settings - Fork 894
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(DocumentContext): Add support for React Portals in new windows & document picture-in-picture #3357
base: main
Are you sure you want to change the base?
Conversation
Thanks for this! It's been on my todo list for a while to fix document references for a while. Curious though why this needs to be a separate context and not a utility function that checks the |
@chaance thanks for quick response! 🫡
|
All valid points when it comes to DX inside of Radix itself but we've made similar decisions with that mindset and I think it's been at the expense of both DX on the consumer's side (the Raect Dev tools components tab is a giant mess) and end user performance. I'd like to recalibrate how we think about and prioritize DX in general. Might not have time to dig into this in depth right away. Competing priorities and whatnot. It's on my TODO list. |
Not sure I understand the impact of the DX on the consumer side though 🤔 - the provider will only ever be used to wrap components passed to ReactDOM.createPortal(
<DocumentContext.Provider value={popupWindow.document}>{content} </DocumentContext.Provider>,
popupWindow.document.body
) So 99% of consumers won't ever have to use the provider in their apps. From the performance POV - the value passed to the provider won't ever change so it won't be causing any unnecessary rerenders. I'm happy to explore other options too, just wanted to better understand your concerns.🫡 |
@arturbien to be clear, I haven't reviewed in depth yet so take my feedback at this stage with a grain of salt :) Initial reaction was assuming that the provider would be used internally but that does not appear to be the case, so I'm open to it. |
Description
This PR adds support for using Radix Primitives in a new window popups and Document Picture in Picture.
Screen.Recording.2025-02-03.at.14.28.30.mov
Use cases
One of the common use cases are popup windows and Document Picture-in-Picture . Document Picture-in-Picture API is used for example by apps like Google Meet where users can enter PIP mode with livestream and chat portalled to a floating window.
This is a use case we're currently facing at Whop, we're building a live-streaming app with Document PIP support.
Why doesn't it work currently in Radix
Since JS and React is running in the parent window, and bunch of components rely on calling
document
, they break when being portalled to a new document. For example when you try to open<Dialog />
or<Tooltip />
in a new document, it will actually open in the parent window, because all event listeners and portals are attached to the parent window.Solution
There were attempts at fixing this before , but the solutions mostly relied on tweaking individual components instead of creating a more global and simpler solution:
#1721
#1676
#1677
#1845
This PR adds an optional
<DocumentContext.Provider value={documentElement} />
component where users can pass reference to the popup window document, anduseDocument()
hook which returns document passed to the provider with a fallback toglobalThis.document
. The hook is used internally within all primitives that rely on thedocument
. All that user has to do to make Radix work with portals to another window is to wrap portalled content with the provider like so:This PR is not introducing any breaking changes or new props to any of the modified components. The provider is completely optional.
TODO:
document
references withprovidedDocument
window
references withprovidedDocument.defaultView
<DocumentContext />
page to the docs website(cc @chaance @benoitgrelard @hugotiger @seleckis @2DTW @gregorybolkenstijn @william-will-angi @LordZardeck @ritz078 @joaodematte)
Closes #1721
Closes #1715