diff --git a/src/renderer/src/components/ContextMenu/index.css b/src/renderer/src/components/ContextMenu/index.css
new file mode 100644
index 0000000..e1cd521
--- /dev/null
+++ b/src/renderer/src/components/ContextMenu/index.css
@@ -0,0 +1,8 @@
+.contextMenu {
+ position: absolute;
+ width: 200px;
+ background-color: #383838;
+ border-radius: 5px;
+ box-sizing: border-box;
+ padding: 0;
+}
\ No newline at end of file
diff --git a/src/renderer/src/components/ContextMenu/index.tsx b/src/renderer/src/components/ContextMenu/index.tsx
new file mode 100644
index 0000000..13fcc6e
--- /dev/null
+++ b/src/renderer/src/components/ContextMenu/index.tsx
@@ -0,0 +1,48 @@
+import { ReactNode, MouseEvent, memo } from 'react';
+import Menu from '../Menu';
+import useContextMenu from '@renderer/hooks/useContextMenu';
+import MenuItem from '../MenuItem';
+
+export interface Item {
+ label: string
+ onClick: () => void
+ show: boolean
+}
+
+interface Props {
+ children: ReactNode
+ items: Item[]
+}
+
+// TODO only one context menu can be opened
+const ContextMenu = ({ children, items }: Props) => {
+ const { menuVisible, menuItems, menuPosition, showMenu, hideMenu } = useContextMenu();
+ const handleContextMenu = (event: MouseEvent) => {
+ showMenu(event, items);
+ };
+
+ return (
+
+ {children}
+
+
+ );
+};
+
+export default memo(ContextMenu);
\ No newline at end of file
diff --git a/src/renderer/src/components/Menu/index.css b/src/renderer/src/components/Menu/index.css
new file mode 100644
index 0000000..e69de29
diff --git a/src/renderer/src/components/Menu/index.tsx b/src/renderer/src/components/Menu/index.tsx
new file mode 100644
index 0000000..69b2e26
--- /dev/null
+++ b/src/renderer/src/components/Menu/index.tsx
@@ -0,0 +1,50 @@
+import { ReactNode } from "react"
+
+interface AnchorPosition {
+ top: number
+ left: number
+}
+interface Props {
+ autoFocus?: boolean
+ children?: ReactNode
+ open: boolean
+ onClose?: (event, reason) => void
+ anchorReference: string
+ anchorPosition: AnchorPosition
+ className: string
+}
+
+const Menu = ({ autoFocus = true, children, open, onClose, anchorReference, anchorPosition, ...rest }: Props) => {
+ const handleListKeyDown = event => {
+ if (event.key === 'Tab') {
+ event.preventDefault();
+ if (onClose) {
+ onClose(event, 'tabKeyDown');
+ }
+ }
+ if (event.key === 'Escape') {
+ event.preventDefault();
+ if (onClose) {
+ onClose(event, 'escapeKeyDown');
+ }
+ }
+ };
+
+ return (
+ <>
+ {open &&
+
+ }
+ >
+ );
+};
+
+export default Menu;
\ No newline at end of file
diff --git a/src/renderer/src/components/MenuItem/index.css b/src/renderer/src/components/MenuItem/index.css
new file mode 100644
index 0000000..e69de29
diff --git a/src/renderer/src/components/MenuItem/index.tsx b/src/renderer/src/components/MenuItem/index.tsx
new file mode 100644
index 0000000..55b4014
--- /dev/null
+++ b/src/renderer/src/components/MenuItem/index.tsx
@@ -0,0 +1,14 @@
+import { ReactNode } from 'react';
+
+interface Props {
+ children: ReactNode
+ onClick: () => void
+}
+
+const MenuItem = ({ children, ...rest }: Props) => {
+ return (
+ {children}
+ );
+};
+
+export default MenuItem;
\ No newline at end of file
diff --git a/src/renderer/src/hooks/useContextMenu.ts b/src/renderer/src/hooks/useContextMenu.ts
new file mode 100644
index 0000000..5ca6baf
--- /dev/null
+++ b/src/renderer/src/hooks/useContextMenu.ts
@@ -0,0 +1,37 @@
+import { useState, useCallback, useEffect } from 'react';
+
+const useContextMenu = () => {
+ const [menuVisible, setMenuVisible] = useState(false);
+ const [menuItems, setMenuItems] = useState([]);
+ const [menuPosition, setMenuPosition] = useState({ x: 0, y: 0 });
+
+ const showMenu = useCallback((event, items) => {
+ event.preventDefault();
+ setMenuPosition({ x: event.pageX, y: event.pageY });
+ setMenuItems(items);
+ setMenuVisible(true);
+ }, []);
+
+ const hideMenu = useCallback(() => {
+ setMenuVisible(false);
+ }, []);
+
+ useEffect(() => {
+ const handleDocumentClick = (event) => {
+ // Logic to hide the context menu
+ hideMenu();
+ };
+
+ // Register the event listener
+ document.addEventListener('click', handleDocumentClick);
+
+ // Cleanup function to remove the event listener
+ return () => {
+ document.removeEventListener('click', handleDocumentClick);
+ };
+ }, [hideMenu]);
+
+ return { menuVisible, menuItems, menuPosition, showMenu, hideMenu };
+};
+
+export default useContextMenu;
\ No newline at end of file