You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This PR improves the focus management when Headless UI components are
used inside of a shadow DOM.
We already tried to not use `document` directly, but instead rely on
`someKnownElement.ownerDocument` to get the correct document context.
This is unfortunately not enough, because if you have a focused element
_inside_ the shadow DOM, then `ownerDocument.activeElement` will return
the wrapping shadow DOM node and not the actual focused element inside
of the shadow DOM.
This PR improves that behavior by using `getRootNode()` instead and then
we read information such as the `activeElement` from there.
It's going to be easier if you look at this reproduction. The element
with the black border is a shadow DOM element. The `toggle` button is a
Popover button.
Expected behavior:
1. You can tab through the elements in order from outside the shadow DOM
into the shadow DOM and out again.
1. You can shift+tab in reverse order as well.
1. When the Popover is open, pressing `Escape` should close the Popover.
1. When tabbing outside of the open popover, the popover should close.
Let's see these things in action:
---
1. Pressing escape on an open Popover should close it
**before:**
https://github.com/user-attachments/assets/99ff5768-f6ac-490f-a607-391bbdd21d65
The reason it doesn't is because we check the `activeElement`, and we
only close the popover if it is the active element. But if you look at
devtools, the button is not the active element so therefore it doesn't
work.
**after:**
https://github.com/user-attachments/assets/22511835-98d3-452d-baac-447fa4e5a5e7
---
2. Tabbing out of an open popover with <kbd>Tab</kbd> should close the
Popover and focus the next element.
**before:**
https://github.com/user-attachments/assets/ab2c5849-f524-436b-aa7c-9e65e5debc67
Here it does all the wrong things, it doesn't go into the PopoverPanel,
it doesn't go to the next button, but it goes to the next button
_outside_ of the shadow dom.
**after:**
https://github.com/user-attachments/assets/c5f653f1-338d-41c4-a166-735e6c1d1435
---
## Test plan
1. Existing code still passes (we don't have shadow DOM tests)
2. Tested the behavior from the reproduction and it all works as
expected now:
https://github.com/user-attachments/assets/a90206e6-ae5e-4748-a4e4-c65dfa69d8f6Fixes: #2951
0 commit comments