All files / app/components EllipsisMenu.tsx

100% Statements 17/17
87.5% Branches 7/8
100% Functions 4/4
100% Lines 15/15

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118  25x 25x 25x 25x   25x                                     260x           25x 260x                                                                                                             401x     18x 18x 18x 18x   18x                                         260x  
import { MoreHoriz, SvgIconComponent } from "@mui/icons-material";
import { IconButton, Menu, styled, Typography } from "@mui/material";
import { useTranslation } from "i18n";
import { GLOBAL } from "i18n/namespaces";
import { theme } from "theme";
 
import { MenuItem } from "./Menu";
 
export interface EllipsisMenuItem {
  icon: SvgIconComponent;
  label: string;
  onClick: () => unknown;
  id?: string;
  shouldCloseMenu?: boolean;
}
 
interface EllipsisMenuProps {
  idName: string;
  isMenuOpen: boolean;
  menuAnchorEl: Element | null;
  onMenuOpen: (event: React.MouseEvent<HTMLButtonElement>) => void;
  onMenuClose: (event: React.MouseEvent<HTMLLIElement>) => void;
  items: EllipsisMenuItem[];
}
 
const MenuWrapper = styled("div")(() => ({
  display: "flex",
  justifyContent: "flex-end",
  flexDirection: "column",
}));
 
const EllipsisMenu = ({ idName, isMenuOpen, menuAnchorEl, onMenuOpen, onMenuClose, items }: EllipsisMenuProps) => {
  const { t } = useTranslation(GLOBAL);
 
  return (
    <MenuWrapper>
      <>
        <IconButton
          aria-label={t("global:more_options_a11y")}
          aria-controls={isMenuOpen ? `${idName}-more-options` : undefined}
          aria-haspopup="true"
          aria-expanded={isMenuOpen ? "true" : undefined}
          id={`${idName}-more-options`}
          data-testid={`${idName}-more-options`}
          onClick={onMenuOpen}
          size="large"
        >
          <MoreHoriz fontSize="small" />
        </IconButton>
        <Menu
          anchorEl={menuAnchorEl}
          id={`${idName}-more-options`}
          data-testid={`${idName}-more-options`}
          open={isMenuOpen}
          onClose={onMenuClose}
          slotProps={{
            paper: {
              elevation: 0,
              sx: {
                overflow: "visible",
                filter: "drop-shadow(0px 2px 8px rgba(0,0,0,0.32))",
                mt: 1.5,
                "& .MuiAvatar-root": {
                  width: 32,
                  height: 32,
                  ml: -0.5,
                  mr: 1,
                },
                "&::before": {
                  content: '""',
                  display: "block",
                  position: "absolute",
                  top: 0,
                  right: 14,
                  width: 10,
                  height: 10,
                  bgcolor: "var(--mui-palette-background-paper)",
                  transform: "translateY(-50%) rotate(45deg)",
                  zIndex: 0,
                },
              },
            },
          }}
          transformOrigin={{ horizontal: "right", vertical: "top" }}
          anchorOrigin={{ horizontal: "right", vertical: "bottom" }}
        >
          {items.map((item, index) => (
            <MenuItem
              key={index}
              onClick={(e) => {
                e.stopPropagation();
                e.preventDefault();
                Eif (item.shouldCloseMenu !== false) {
                  onMenuClose(e);
                }
                item.onClick();
              }}
              {...(item.id
                ? {
                    id: `${idName}-${item.id}`,
                    "data-testid": `${idName}-${item.id}`,
                  }
                : {})}
            >
              <item.icon fontSize="small" />
              <Typography variant="body2" sx={{ marginLeft: theme.spacing(1), fontWeight: 500 }}>
                {item.label}
              </Typography>
            </MenuItem>
          ))}
        </Menu>
      </>
    </MenuWrapper>
  );
};
 
export default EllipsisMenu;