I've been using @headlessui/react for a project and it's helped me be very productive! But I've found an issue where one component interferes with another. I think I've found the general area of the issue and can provide a reproduction but I want to know:
- Why specifically is this happening?
- What solutions might fix this behavior either as a workaround or within the headlessui/react library itself?
The Issue
When using the Popover
component within a Tab.Panel
component, the Popover.Panel
does not behave correctly. According to the docs:
When the panel is open, clicking anywhere outside of its contents, pressing the Escape key, or tabbing away from it will close the Popover.
However, when the Popover
is within a Tab
component (docs) the behavior is inconsistent. For me, in Chrome, clicks within the Popover.Panel
close the panel unless the click is on a button
and in Safari the panel closes in all cases. Focusing the button with the keyboard allows selection though.
Reproduction
I created a simplified version of the issue in codesandbox
I think this has something to do with the Tab
component capturing the focus
from the Popover.Panel
which in turn closes the Popover.Panel
.
I added this snippet from "Console logging the focused element as it changes" to the reproduction and the Tab.Panel
seems to have the focus
after clicking in Popover.Panel
:
document.addEventListener(
"focusin",
function () {
console.log("focused: ", document.activeElement);
},
true
);
Can anyone provide an explanation of what is happening and suggestions for simple remedies?
I can now answer why specifically this is happening and also provide a possible solution.
I was able to simplify my case a bit. This will happen whenever
Popover
is inside a focusable element (whichTab.Panel
is). I think it's here in the PopoverRoot that whenever the activeElement is outside of the group the panel is closed.If the
Popover
is inside an element withtabindex="0"
then that element will be theactiveElement
and the panel will be closed. I updated the codesandbox reproduction to demo this without usingTab
and also propose a workaround but I'm not sure if it's an appropriate solution or not.The workaround appears to be just adding
tabIndex="0"
to thePopover.Panel
so that it is theactiveElement
. Is there a reason this shouldn't be done or could cause other unexpected behavior?