21842: fixed lost anchorEl bug
[arvados.git] / services / workbench2 / src / components / popover / popover.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import React from 'react';
6 import { Popover as MaterialPopover } from '@mui/material';
7
8 import { PopoverOrigin } from '@mui/material/Popover';
9 import IconButton, { IconButtonProps } from '@mui/material/IconButton';
10
11 export interface PopoverProps {
12     triggerComponent?: React.ComponentType<{ onClick: (event: React.MouseEvent<any>) => void }>;
13     closeOnContentClick?: boolean;
14 }
15
16 export class Popover extends React.Component<PopoverProps> {
17     state = {
18         anchorEl: undefined
19     };
20
21     transformOrigin: PopoverOrigin = {
22         vertical: "top",
23         horizontal: "right",
24     };
25
26     render() {
27         const Trigger = this.props.triggerComponent || DefaultTrigger;
28         return (
29             <>
30                 <Trigger onClick={this.handleTriggerClick} />
31                 <MaterialPopover
32                     data-cy="popover"
33                     anchorEl={this.state.anchorEl}
34                     open={Boolean(this.state.anchorEl)}
35                     onClose={this.handleClose}
36                     onClick={this.handleSelfClick}
37                     transformOrigin={this.transformOrigin}
38                     anchorOrigin={this.transformOrigin}
39                 >
40                     {this.props.children}
41                 </MaterialPopover>
42             </>
43         );
44     }
45
46     handleClose = () => {
47         this.setState({ anchorEl: undefined });
48     }
49
50     handleTriggerClick = (event: React.MouseEvent<any>) => {
51         this.setState({ anchorEl: event.currentTarget });
52     }
53
54     handleSelfClick = () => {
55         if (this.props.closeOnContentClick) {
56             this.handleClose();
57         }
58     }
59 }
60
61 export const DefaultTrigger: React.SFC<IconButtonProps> = (props) => (
62     <IconButton {...props} size="large">
63         <i className="fas" />
64     </IconButton>
65 );