-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Ensure moving focus within a Portal
component, does not close the Popover
component
#2492
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
'Portal', | ||
'Combobox', | ||
'Dialog', | ||
'Disclosure', | ||
'FocusTrap', | ||
'Listbox', | ||
'Menu', | ||
'Popover', | ||
'Portal', | ||
'RadioGroup', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be sorted alphabetically? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are, but the exports are sorted alphabetically and the export for the portal itself changed which is now hoisted to the top in the test.
This way we can reuse it in other components when needed.
8d1fda3
to
488a206
Compare
488a206
to
00ce35e
Compare
This allows us to find all the `Portal` components that are nested in a given component without manually adding refs to every `Portal` component itself. This will come in handy in the `Popover` component where we will allow focus in the child `Portal` components otherwise a focus outside of the `Popover` will close the it. In other components we often crawl the DOM directly using `[data-headlessui-portal]` data attributes, however this will fetch _all_ the `Portal` components, not the ones that started in the current component.
The `Popover` component will close by default if focus is moved outside of it. However, if you use a `Portal` comopnent inside the `Popover.Panel` then from a DOM perspective you are moving the focus outside of the `Popover.Panel`. This prevents the closing, and allows the focus into the `Portal`. It currently only allows for `Portal` components that originated from the `Popover` component. This means that if you open a `Dialog` component from within the `Popover` component, the `Dialog` already renders a `Portal` but since this is part of the `Dialog` and not the `Popover` it will close the `Popover` when focus is moved to the `Dialog` component.
This ensures that if you have a structure like this: ```jsx <Dialog> {/* Renders a portal internally */} <Popover> <Portal> {/* First level */} <Popover.Panel> <Menu> <Portal> {/* Second level */} <Menu.Items> {/* ... */} </Menu.Items> </Portal> </Menu> </Popover.Panel> </Portal> </Popover> </Dialog> ``` That working with the `Menu` doesn't close the `Popover` or the `Dialog`.
This will allow you to pass in portal elements as well. + cleanup of the resolving of all DOM nodes.
Shorthand to check if any of the root containers contains the given element.
00ce35e
to
5ceed37
Compare
To make it similar between React & Vue
The
Popover
component closes automatically if the focus is moved outside of thePopover.Panel
. However, this also happens if you render aPortal
component inside thePopover.Panel
and move focus within thatPortal
component.From a DOM perspective, the focus is not in the
Popover.Panel
anymore, so therefore it will close. This PR fixes that issue and will allow focus inPortal
components that originate from within thePopover.Panel
component. We can use the React tree (using the Context API) to see if a certain DOM element is still nested from a React's perspective.This PR also makes sure that only
Portal
components that originate from thePopover
component will be marked as a validPortal
location. If you trigger the opening of a siblingDialog
component from within thePopover.Panel
component, then focus moving into theDialog
will close thePopover
component.Fixes: #2481