Skip to content

Commit 1ec0b27

Browse files
committed
fix(click-away): fix close on click away across shadow DOM boundary
1 parent 46758a3 commit 1ec0b27

File tree

3 files changed

+11
-15
lines changed

3 files changed

+11
-15
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Fixed
11+
12+
- `Popover`, `Dialog` & `Lightbox`: fix close on click away across shadow DOM boundary
13+
1014
### Added
1115

1216
- `ExpansionPanel`: added `closeMode` to `"unmount"` or `"hide"` children when the item is closed.

packages/lumx-react/src/hooks/useClickAway.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import isEmpty from 'lodash/isEmpty';
66

77
const EVENT_TYPES = ['mousedown', 'touchstart'];
88

9-
function isClickAway(target: HTMLElement, refs: Array<RefObject<HTMLElement>>): boolean {
10-
// The target element is not contained in any of the listed element references.
11-
return !refs.some((e) => e?.current?.contains(target));
9+
function isClickAway(targets: HTMLElement[], refs: Array<RefObject<HTMLElement>>): boolean {
10+
// The targets elements are not contained in any of the listed element references.
11+
return !refs.some((ref) => targets.some((target) => ref?.current?.contains(target)));
1212
}
1313

1414
export interface ClickAwayParameters {
@@ -34,8 +34,8 @@ export function useClickAway({ callback, childrenRefs }: ClickAwayParameters): v
3434
return undefined;
3535
}
3636
const listener: EventListener = (evt) => {
37-
const target = evt.composedPath?.()[0] || evt.target;
38-
if (isClickAway(target as HTMLElement, currentRefs)) {
37+
const targets = [evt.composedPath?.()[0], evt.target] as HTMLElement[];
38+
if (isClickAway(targets, currentRefs)) {
3939
callback(evt);
4040
}
4141
};

packages/lumx-react/src/utils/ClickAwayProvider/ClickAwayProvider.stories.jsx

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
/* eslint-disable react-hooks/rules-of-hooks */
22
/* eslint-disable @typescript-eslint/no-use-before-define */
33
import React, { useCallback, useRef, useState } from 'react';
4-
import { Button, Popover } from '@lumx/react';
4+
import { Button } from '@lumx/react';
55
import { ClickAwayProvider } from '@lumx/react/utils/ClickAwayProvider';
66
import { initDemoShadowDOMPortal } from '@lumx/react/stories/utils/initDemoShadowDOMPortal';
77
import { PortalProvider, Portal } from '@lumx/react/utils/Portal';
8-
import { useBooleanState } from '@lumx/react/hooks/useBooleanState';
98

109
export default {
1110
title: 'LumX components/ClickAwayProvider',
@@ -63,16 +62,9 @@ export const NestedClickAway = () => (
6362
* Testing close on click away for a popover rendered in a shadow DOM
6463
*/
6564
export const InShadowDOM = () => {
66-
const [isOpen, close, , toggle] = useBooleanState(false);
67-
const anchorRef = React.useRef();
6865
return (
6966
<PortalProvider value={initDemoShadowDOMPortal}>
70-
<Button ref={anchorRef} onClick={toggle}>
71-
Toggle popover
72-
</Button>
73-
<Popover isOpen={isOpen} anchorRef={anchorRef} onClose={close} closeOnClickAway>
74-
<p style={{ padding: 16, border: '1px solid gray' }}>Popover in shadow DOM</p>
75-
</Popover>
67+
<NestedClickAway />
7668
</PortalProvider>
7769
);
7870
};

0 commit comments

Comments
 (0)