ui icon indicating copy to clipboard operation
ui copied to clipboard

Overlay immediately closes with rootClose in shadow root

Open angrycat9000 opened this issue 2 years ago • 11 comments

Describe the bug

Overlay with rootClose closes as soon as it is opened if it is hosted inside of a custom element shadow root.

I'm using custom elements to isolate some react based components that are hosted in an older application. The Overlay immediately closes when opened if it is hosted inside of a shadow root of a custom element. The same code works correctly when hosted in the light dom.

To Reproduce

Steps to reproduce the behavior:

  1. Create a custom element with a shadow root that hosts a react render root
  2. Render a Overlay with rootClose and onHide set. Also have the container option point to an element in the shadow root
  3. Click the button to open the overlay.

Reproducible Example

https://codesandbox.io/s/bold-dan-5kfh5r - Declares a custom element in index.js and has it render the same React component as is rendered in the light DOM. The custom element embedded version does not work, the light DOM version does.

  • Click the Show in shadow root button. Note the popover flashes and then disappears.
  • Click Show in light DOM button. Note that the popover appears and remains visibile.

Expected behavior

The popover remains open until an additional click.

Screenshots

Screencast from 08-08-2023 10:04:38 AM.webm

Environment (please complete the following information)

  • Operating System: Linux
  • Browser, Version: Chrome 115.0.5790.110 image

Additional context

This seems to be related to a change between React 17 and React 18. Was not able to reproduce it using React 17 or the legacy ReactDOM.render method in React 18.

angrycat9000 avatar Aug 08 '23 14:08 angrycat9000

The original workaround that @jquense added to fix this doesn't work in the shadow DOM because currentEvent is undefined

https://github.com/react-restart/ui/blob/44dc346744b37c33bd0d0309e5cd827751fce9c4/src/useClickOutside.ts#L104C9-L104C9

As a result, the click handler is processing twice

kyletsang avatar Aug 09 '23 04:08 kyletsang

Funny I just saw that material UI has a different work around for the same issue in their ClickAway component, maybe we can try that?

jquense avatar Aug 09 '23 22:08 jquense

Funny I just saw that material UI has a different work around for the same issue in their ClickAway component, maybe we can try that?

Unfortunately couldn't get tests to pass with the MUI approach. I'll need to drop this for now, since I'm short on time ATM.

kyletsang avatar Aug 17 '23 02:08 kyletsang

fair enough, i don't think this is a super pressing use case anyway!

jquense avatar Aug 17 '23 13:08 jquense

Hi, any update? Do you need some help to make test passing? I'd like to make it work as soon as possible as the whole react-bootstrap is not working in the shadowDOM.

This issue is also visible for Dropdowns. In the shadow tree, dropdown is opened and immediately closed.

mklekowski avatar May 29 '24 10:05 mklekowski

FYI @mklekowski I ended up working around this by not using rootClose and then adding my own event listeners for Escape and a click outside the overlay.

angrycat9000 avatar May 29 '24 12:05 angrycat9000

Actually, I have an issue with DropdownButton, when clicking two events are triggered, first for opening and second for closing. Probably it's also possible to disable rootClose and implement it manually, but I prefer to fix it in the library directly.

@jquense can you look at the issue?

mklekowski avatar Jun 03 '24 08:06 mklekowski

Also, the code is using Window/event which is deprecated. Maybe it can be implemented in different way?

mklekowski avatar Jun 03 '24 08:06 mklekowski

Actually, I have an issue with DropdownButton, when clicking two events are triggered, first for opening and second for closing. Probably it's also possible to disable rootClose and implement it manually, but I prefer to fix it in the library directly.

@mklekowski do you have a workaround? I have the same issue as you, with DropdownButton.

HighLiuk avatar Jul 08 '24 10:07 HighLiuk

Yes and no :) The workaround for me was to change usage of the library to mui/base-ui - it has better support for shadow dom and it looks like it's better maintained.

mklekowski avatar Jul 08 '24 10:07 mklekowski

Yes and no :) The workaround for me was to change usage of the library to mui/base-ui - it has better support for shadow dom and it looks like it's better maintained.

Ouch - thank you anyway - I'm bound to Bootstrap though, so hopefully this gets fixed soon. My current workaround is

    <Dropdown
      autoClose="outside"
      show={showDropdown}
      onToggle={(show, meta) => {
        const target = meta.originalEvent?.target as HTMLElement;

        if (target.tagName !== "DROP-DOWN") { // "drop-down" is my custom element name
          setShowDropdown(show);
        }
      }}
    >
    </Dropdown>

This makes the Dropdown kinda work, but it doesn't close the menu when you click inside the custom element but outside the button.

HighLiuk avatar Jul 08 '24 11:07 HighLiuk