Skip to content

Commit 1704aa4

Browse files
authored
Merge pull request #271 from logonoff/fix
fix(ContextSubMenuItem): fix popper container
2 parents dc28e8b + 126476a commit 1704aa4

File tree

1 file changed

+28
-14
lines changed

1 file changed

+28
-14
lines changed

packages/module/src/components/contextmenu/ContextSubMenuItem.tsx

+28-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as React from 'react';
2-
import { Dropdown, DropdownItem } from '@patternfly/react-core';
2+
import { Menu, DropdownItem } from '@patternfly/react-core';
33
import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon';
44
import { css } from '@patternfly/react-styles';
55
import topologyStyles from '../../css/topology-components';
@@ -11,6 +11,17 @@ interface ContextSubMenuItemProps {
1111
children: React.ReactNode[];
1212
}
1313

14+
/**
15+
* Check if an event target implements the [DOM Node interface][1].
16+
* Needed to prevent runtime errors where the event target is not a DOM node,
17+
* but `contains` is still called on it.
18+
*
19+
* [1]: https://developer.mozilla.org/en-US/docs/Web/API/Node
20+
*/
21+
const implementsDOMNode = (node: any): boolean => {
22+
return node && typeof node === 'object' && node.nodeType && node.nodeName;
23+
};
24+
1425
const ContextSubMenuItem: React.FunctionComponent<ContextSubMenuItemProps> = ({ label, children, ...other }) => {
1526
const nodeRef = React.useRef<HTMLButtonElement>(null);
1627
const subMenuRef = React.useRef<HTMLDivElement>(null);
@@ -29,7 +40,10 @@ const ContextSubMenuItem: React.FunctionComponent<ContextSubMenuItemProps> = ({
2940
onMouseEnter={() => setOpen(true)}
3041
onMouseLeave={(e) => {
3142
// if the mouse leaves this item, close the sub menu only if the mouse did not enter the sub menu itself
32-
if (!subMenuRef.current || !subMenuRef.current.contains(e.relatedTarget as Node)) {
43+
if (
44+
!subMenuRef.current ||
45+
(implementsDOMNode(e.relatedTarget) && !subMenuRef.current.contains(e.relatedTarget as Node))
46+
) {
3347
setOpen(false);
3448
}
3549
}}
@@ -51,22 +65,21 @@ const ContextSubMenuItem: React.FunctionComponent<ContextSubMenuItemProps> = ({
5165
closeOnOutsideClick
5266
onRequestClose={(e) => {
5367
// only close the sub menu if clicking anywhere outside the menu item that owns the sub menu
54-
if (!e || !nodeRef.current || !nodeRef.current.contains(e.target as Node)) {
68+
if (!e || !nodeRef.current || (implementsDOMNode(e.target) && !nodeRef.current.contains(e.target as Node))) {
5569
setOpen(false);
5670
}
5771
}}
5872
reference={referenceCb}
59-
// use the parent node to capture the li
60-
container={nodeRef.current ? nodeRef.current.parentElement : nodeRef.current}
73+
container={nodeRef.current?.closest('.pf-v6-c-menu__content')}
6174
returnFocus
6275
>
63-
<div
64-
ref={subMenuRef}
65-
role="presentation"
66-
className="pf-v6-c-dropdown pf-m-expanded"
76+
<Menu
6777
onMouseLeave={(e) => {
6878
// only close the sub menu if the mouse does not enter the item
69-
if (!nodeRef.current || !nodeRef.current.contains(e.relatedTarget as Node)) {
79+
if (
80+
!nodeRef.current ||
81+
(implementsDOMNode(e.relatedTarget) && !nodeRef.current.contains(e.relatedTarget as Node))
82+
) {
7083
setOpen(false);
7184
}
7285
}}
@@ -77,11 +90,12 @@ const ContextSubMenuItem: React.FunctionComponent<ContextSubMenuItemProps> = ({
7790
e.stopPropagation();
7891
}
7992
}}
93+
ref={subMenuRef}
94+
role="presentation"
95+
isNavFlyout
8096
>
81-
<Dropdown toggle={() => <></>} className={css(topologyStyles.topologyContextMenuCDropdownMenu)}>
82-
{children}
83-
</Dropdown>
84-
</div>
97+
{children}
98+
</Menu>
8599
</Popper>
86100
</>
87101
);

0 commit comments

Comments
 (0)