22207: reimplemented altNames for toggleable menu items
[arvados.git] / services / workbench2 / src / components / multiselect-toolbar / ms-toolbar-overflow-menu.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import React, { useState, useMemo, ReactElement, JSXElementConstructor } from 'react';
6 import { DoubleRightArrows } from 'components/icon/icon';
7 import classnames from 'classnames';
8 import { CustomStyleRulesCallback } from 'common/custom-theme';
9 import { IconButton, Menu, MenuItem, Tooltip } from '@mui/material';
10 import { WithStyles } from '@mui/styles';
11 import withStyles from '@mui/styles/withStyles';
12 import { ArvadosTheme } from 'common/custom-theme';
13
14 type CssRules = 'inOverflowMenu' | 'openMenuButton' | 'menu' | 'menuItem' | 'menuElement';
15
16 const styles: CustomStyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
17     inOverflowMenu: {
18         '&:hover': {
19             backgroundColor: 'transparent',
20         },
21     },
22     openMenuButton: {
23         right: '10px',
24     },
25     menu: {
26         marginLeft: 0,
27     },
28     menuItem: {
29         '&:hover': {
30             backgroundColor: 'white',
31         },
32         marginTop: 0,
33         paddingTop: 0,
34         paddingLeft: '1rem',
35         height: '2.5rem',
36     },
37     menuElement: {
38         width: '2rem',
39     }
40 });
41
42 export type OverflowChild = ReactElement<{ className: string; }, string | JSXElementConstructor<any>>
43
44 type OverflowMenuProps = {
45     children: OverflowChild[]
46     className: string
47     visibilityMap: {}
48 }
49
50 export const OverflowMenu = withStyles(styles)((props: OverflowMenuProps & WithStyles<CssRules>) => {
51     const { children, className, visibilityMap, classes } = props;
52     const [anchorEl, setAnchorEl] = useState(null);
53     const open = Boolean(anchorEl);
54     const handleClick = (event) => {
55         setAnchorEl(event.currentTarget);
56     };
57
58     const handleClose = () => {
59         setAnchorEl(null);
60     };
61
62     const shouldShowMenu = useMemo(() => Object.values(visibilityMap).some((v) => v === false), [visibilityMap]);
63     if (!shouldShowMenu) {
64         return null;
65     }
66     return (
67         <div className={className}>
68             <Tooltip title="More options" disableFocusListener>
69                 <IconButton
70                     aria-label='more'
71                     aria-controls='long-menu'
72                     aria-haspopup='true'
73                     onClick={handleClick}
74                     className={classes.openMenuButton}
75                     data-cy='overflow-menu-button'
76                     size="large">
77                         <DoubleRightArrows />
78                 </IconButton>
79             </Tooltip>
80             <Menu
81                 id='long-menu'
82                 anchorEl={anchorEl}
83                 keepMounted
84                 open={open}
85                 onClose={handleClose}
86                 disableAutoFocusItem
87                 className={classes.menu}
88                 data-cy='overflow-menu'
89             >
90                 {React.Children.map(children, (child: any) => {
91                     if (!visibilityMap[child.props['data-targetid']]) {
92                         return (
93                             <Tooltip
94                                 title={child.props['data-title']}
95                                 key={child.props['data-targetid']}
96                                 disableFocusListener
97                                 placement='left-start'
98                             >
99                                 <MenuItem
100                                     key={child}
101                                     onClick={handleClose}
102                                     className={classes.menuItem}
103                                     >
104                                     {React.cloneElement(child, {
105                                         className: classnames(classes.menuElement),
106                                     })}
107                                 </MenuItem>
108                         </Tooltip>)
109                     }
110                     return null;
111                 })}
112             </Menu>
113         </div>
114     );
115 });