Uniformize styles for dialogs and popovers, add ContextMenu
Change-Id: I8687b2d171f9c15e8eb8dd5ba2a32cdaa27b70d6
diff --git a/client/src/components/ContextMenu.tsx b/client/src/components/ContextMenu.tsx
new file mode 100644
index 0000000..6ac1363
--- /dev/null
+++ b/client/src/components/ContextMenu.tsx
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2022 Savoir-faire Linux Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+import { Menu, MenuProps, PopoverPosition, PopoverReference, styled } from '@mui/material';
+import { MouseEventHandler, useCallback, useMemo, useState } from 'react';
+
+import PopoverList, { PopoverListItemData } from './PopoverList';
+
+export interface ContextMenuHandler {
+ props: {
+ open: boolean;
+ onClose: () => void;
+ anchorPosition: PopoverPosition | undefined;
+ anchorReference: PopoverReference | undefined;
+ };
+ handleAnchorPosition: MouseEventHandler;
+}
+
+export const useContextMenuHandler = (): ContextMenuHandler => {
+ const [anchorPosition, setAnchorPosition] = useState<PopoverPosition | undefined>(undefined);
+
+ const handleAnchorPosition = useCallback<MouseEventHandler>(
+ (event) => {
+ event.preventDefault();
+ setAnchorPosition((anchorPosition) =>
+ anchorPosition === undefined ? { top: event.clientY, left: event.clientX } : undefined
+ );
+ },
+ [setAnchorPosition]
+ );
+
+ const onClose = useCallback(() => setAnchorPosition(undefined), [setAnchorPosition]);
+
+ return useMemo(
+ () => ({
+ props: {
+ open: !!anchorPosition,
+ onClose,
+ anchorPosition,
+ anchorReference: 'anchorPosition',
+ },
+ handleAnchorPosition,
+ }),
+ [anchorPosition, handleAnchorPosition, onClose]
+ );
+};
+
+interface ContextMenuProps extends MenuProps {
+ items: PopoverListItemData[];
+}
+
+const ContextMenu = styled(({ items, ...props }: ContextMenuProps) => (
+ <Menu {...props}>
+ <PopoverList items={items} onClose={props.onClose} />
+ </Menu>
+))(() => ({
+ '& .MuiPaper-root': {
+ borderRadius: '5px 20px 20px 20px',
+ boxShadow: '3px 3px 7px #00000029',
+ },
+ '& .MuiMenu-list': {
+ padding: '0px',
+ },
+}));
+
+export default ContextMenu;