Merge branch '21448-menu-reorder' into 21224-project-details
[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 '@material-ui/core';
7
8 import { PopoverOrigin } from '@material-ui/core/Popover';
9 import IconButton, { IconButtonProps } from '@material-ui/core/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                     anchorEl={this.state.anchorEl}
33                     open={Boolean(this.state.anchorEl)}
34                     onClose={this.handleClose}
35                     onClick={this.handleSelfClick}
36                     transformOrigin={this.transformOrigin}
37                     anchorOrigin={this.transformOrigin}
38                 >
39                     {this.props.children}
40                 </MaterialPopover>
41             </>
42         );
43     }
44
45     handleClose = () => {
46         this.setState({ anchorEl: undefined });
47     }
48
49     handleTriggerClick = (event: React.MouseEvent<any>) => {
50         this.setState({ anchorEl: event.currentTarget });
51     }
52
53     handleSelfClick = () => {
54         if (this.props.closeOnContentClick) {
55             this.handleClose();
56         }
57     }
58 }
59
60 export const DefaultTrigger: React.SFC<IconButtonProps> = (props) => (
61     <IconButton {...props}>
62         <i className="fas" />
63     </IconButton>
64 );