-
Notifications
You must be signed in to change notification settings - Fork 43
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
cant use useOutsideClick function #210
Comments
We had a similar issue come up in Discord a while back. This wouldn't happen unless using Shadow DOM, but one of the isolation features of Shadow DOM is that it scrubs references to elements within the shadow root when bubbling events up to the light DOM. One strategy you might consider is having your component manage its own modal backdrop that will catch clicks outside of the modal. Also you might attach this handler at the shadow root and use a different handler that looks for clicks outside of the containing custom element attached at the document level. Let me know if you need code examples. |
@bmomberger-bitovi thanks for the answer, could you give me some code examples. |
To create a modal backdrop, you should only need to do something like this: <>
<div
style={{
position: "fixed",
left: 0,
top: 0,
width: "100vw",
height: "100vh",
backgroundColor: "rgba(32, 32, 32, 0.3)",
zIndex: -1, /* z-index may need to be adjusted here or in the other modal items */
}}
onClick={() => callback()}
>
</div>
// ... the rest of your modal content goes here:
</> |
Adapting your useOutsideClick effect to support shadow roots (can be used with or without the modal backdrop above) const useOutsideClickk = (callback) => {
const ref = useRef();
useEffect(() => {
if(ref.current) {
const element = ref.current;
const innerHandler = (ev) => {
if(!element.contains(ev.target) {
// click was outside the testing element, but within the shadow DOM
callback();
}
};
let outerHandler;
const root = element.getRootNode(); //in shadow DOM will return the shadow root, in light DOM will return the document
root.addEventListener('click', callback, false);
if (root !== document) {
const { host } = root; // surprisingly, this works even in closed shadow mode -- `host` is the element holding the shadow root
outerHandler = (ev) => {
if (ev.target !== host) {
// click originated from outside the component's shadow DOM entirely
callback();
}
};
document.addEventListener('click', outerHandler, false);
}
return () => {
root.removeEventListener('click', innerHandler, false);
if (outerHandler) {
document.removeEventListener('click', outerHandler, false);
}
}
}
}, [callback]);
return ref;
}; |
The above code assumes that you will only ever attach a component into the light DOM. The outerHandler could be rewriten as a loop if you have shadow DOM nesting inside shadow DOM. You would need to hold references to each attachment point and each handler you make, in an array or Map. You know when to terminate the loop when |
I have a modal in the web component which should close when you click outside. However, this does not work with the following code, because event.target only returns the web component.
The text was updated successfully, but these errors were encountered: