Skip to content
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

[Bug]: Popover not working inside Web Component #514

Closed
JaapWeijland opened this issue May 12, 2021 · 6 comments
Closed

[Bug]: Popover not working inside Web Component #514

JaapWeijland opened this issue May 12, 2021 · 6 comments

Comments

@JaapWeijland
Copy link

JaapWeijland commented May 12, 2021

What package within Headless UI are you using?

@headlessui/react

What version of that package are you using?

1.2.0

What browser are you using?

Chrome

Reproduction repository

None

Describe your issue

When using popover inside a web component, the popover panel closes even when you click inside the panel. I am using the most minimal example of the docs. When I pull this code outside my web component into my "root" react application, it works as expected.

Used code:

const Example: React.FC<{}> = () => {
    return (
        <Popover className="relative">
            <Popover.Button>Solutions</Popover.Button>

            <Popover.Panel className="absolute z-10">
                <div className="grid grid-cols-2">
                    <a href="/analytics">Analytics</a>
                    <a href="/engagement">Engagement</a>
                    <a href="/security">Security</a>
                    <a href="/integrations">Integrations</a>
                </div>

                <img src="/solutions.jpg" alt="" />
            </Popover.Panel>
        </Popover>
    );
};

When using this code inside my web component, clicking inside the panel will close the popover.

@JaapWeijland
Copy link
Author

JaapWeijland commented May 12, 2021

Update: I did some digging and I think the problem is with this line:

(button?.contains(document.activeElement) || panel?.contains(document.activeElement))

This line only checks what the active element is within the "root tree", but if the active element is inside a shadow tree, the whole custom element will be returned as the active element, and since that element does not live inside the popover panel, it concludes somewhere outside the panel is clicked on.

The following article helped me in understanding this: https://dev.to/open-wc/mind-the-document-activeelement-2o9a

Update #2: It could also be related to the way the target of the mousedown is determined:

let target = event.target as HTMLElement

Now, event.target is used as target, returning my whole webcomponent as the target. When using event.path[0] as target instead, the actual element within my web component is returned. Changing this could fix this issue with web components with a 'open' shadow root.

@herodrigues
Copy link

I can confirm that.
I'm trying to use a modal in a browser extension that is rendered to a shadow root element.

The modal is rendered on document root instead of shadow root.

@zawilliams
Copy link

@herodrigues I'm also trying to render to shadow root. I'm actually trying to do this with the Dialog component.

@xylophonehero
Copy link

I'm having the same problem with the Menu component inside a shadow root. Clicks on the items work fine but when trying to select an item by focus it doesn't work.

document.getElementById(id)?.click()

Using document.getElementById(id) doesn't work if the element is inside the shadow root.

@herodrigues
Copy link

@zawilliams my "solution" was not to use any modal component. Instead, I replaced every modal with a normal div and emulated the modal behaviour;

@RobinMalfait
Copy link
Member

Hey! Thank you for your bug report!
Much appreciated! 🙏

We currently don't have web components support, but I captured this in a separate discussion so that we can clean things up. Discussion: #874

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants