diff --git a/packages/usehooks-ts/src/index.ts b/packages/usehooks-ts/src/index.ts
index 9577bd16..da4c51b5 100644
--- a/packages/usehooks-ts/src/index.ts
+++ b/packages/usehooks-ts/src/index.ts
@@ -2,6 +2,7 @@ export * from './useBoolean'
export * from './useClickAnyWhere'
export * from './useCopyToClipboard'
export * from './useCountdown'
+export * from './useContextMenu'
export * from './useCounter'
export * from './useDarkMode'
export * from './useDebounceCallback'
diff --git a/packages/usehooks-ts/src/useContextMenu/index.ts b/packages/usehooks-ts/src/useContextMenu/index.ts
new file mode 100644
index 00000000..9c94058c
--- /dev/null
+++ b/packages/usehooks-ts/src/useContextMenu/index.ts
@@ -0,0 +1 @@
+export * from './useContextMenu'
diff --git a/packages/usehooks-ts/src/useContextMenu/useContextMenu.demo.tsx b/packages/usehooks-ts/src/useContextMenu/useContextMenu.demo.tsx
new file mode 100644
index 00000000..8f15d2a5
--- /dev/null
+++ b/packages/usehooks-ts/src/useContextMenu/useContextMenu.demo.tsx
@@ -0,0 +1,38 @@
+import React from 'react';
+import { useContextMenu } from './useContextMenu';
+
+const Component: React.FC = () => {
+ const { isOpen, setIsOpen, position, handleContextMenu } = useContextMenu();
+
+ return (
+
+
Right-click anywhere to open the context menu
+ {isOpen && (
+
+ )}
+
+ );
+};
+
+export default Component;
diff --git a/packages/usehooks-ts/src/useContextMenu/useContextMenu.md b/packages/usehooks-ts/src/useContextMenu/useContextMenu.md
new file mode 100644
index 00000000..13c847a4
--- /dev/null
+++ b/packages/usehooks-ts/src/useContextMenu/useContextMenu.md
@@ -0,0 +1,14 @@
+# useContextMenu Hook
+
+`useContextMenu` is a custom React hook that helps manage the visibility and position of a context menu. It tracks whether the menu is open or closed and updates its position based on the user's right-click location.
+
+## Features
+- Manage the visibility state of a context menu.
+- Position the menu precisely based on the right-click coordinates.
+- Automatically close the menu when the user clicks anywhere outside of it.
+
+## Installation
+To use this hook, simply copy the `useContextMenu` code into your project.
+
+```typescript
+import { useContextMenu } from 'usehooks-ts';
diff --git a/packages/usehooks-ts/src/useContextMenu/useContextMenu.test.ts b/packages/usehooks-ts/src/useContextMenu/useContextMenu.test.ts
new file mode 100644
index 00000000..d1ce6035
--- /dev/null
+++ b/packages/usehooks-ts/src/useContextMenu/useContextMenu.test.ts
@@ -0,0 +1,50 @@
+import { renderHook, act } from '@testing-library/react-hooks';
+import { useContextMenu } from './useContextMenu';
+
+describe('useContextMenu', () => {
+ test('should initialize with default values', () => {
+ const { result } = renderHook(() => useContextMenu());
+
+ expect(result.current.isOpen).toBe(false);
+ expect(result.current.position).toEqual({ x: 0, y: 0 });
+ });
+
+ test('should initialize with provided initial values', () => {
+ const initialOpen = true;
+ const initialPosition = { x: 50, y: 50 };
+ const { result } = renderHook(() => useContextMenu(initialOpen, initialPosition));
+
+ expect(result.current.isOpen).toBe(true);
+ expect(result.current.position).toEqual(initialPosition);
+ });
+
+ test('should toggle isOpen state', () => {
+ const { result } = renderHook(() => useContextMenu());
+
+ act(() => result.current.setIsOpen(true));
+ expect(result.current.isOpen).toBe(true);
+
+ act(() => result.current.setIsOpen(false));
+ expect(result.current.isOpen).toBe(false);
+ });
+
+ test('should update position state', () => {
+ const { result } = renderHook(() => useContextMenu());
+
+ const newPosition = { x: 20, y: 20 };
+ act(() => result.current.setPosition(newPosition));
+ expect(result.current.position).toEqual(newPosition);
+ });
+
+ test('should close context menu when document is clicked', () => {
+ const { result } = renderHook(() => useContextMenu(true));
+
+ expect(result.current.isOpen).toBe(true);
+
+ act(() => {
+ document.dispatchEvent(new MouseEvent('click', { bubbles: true }));
+ });
+
+ expect(result.current.isOpen).toBe(false);
+ });
+});
diff --git a/packages/usehooks-ts/src/useContextMenu/useContextMenu.ts b/packages/usehooks-ts/src/useContextMenu/useContextMenu.ts
new file mode 100644
index 00000000..0e1d8136
--- /dev/null
+++ b/packages/usehooks-ts/src/useContextMenu/useContextMenu.ts
@@ -0,0 +1,79 @@
+import { useEffect, useState } from 'react';
+import type { Dispatch, SetStateAction, MouseEvent } from 'react';
+
+/**
+ * Structure of the return value for `useContextMenu`.
+ */
+type UseContextMenuReturn = {
+ /** State indicating if the context menu is open. */
+ isOpen: boolean;
+ /** Coordinates for the context menu position. */
+ position: {
+ x: number;
+ y: number;
+ };
+ /** Toggle function for the `isOpen` state. */
+ setIsOpen: Dispatch>;
+ /** Function to update the context menu position. */
+ setPosition: Dispatch>;
+ /** Function to handle right-click to open the context menu at cursor position. */
+ handleContextMenu: (event: MouseEvent) => void;
+};
+
+/**
+ * Custom hook to manage a context menu's visibility and position.
+ *
+ * This hook provides:
+ * - `isOpen`: Boolean state indicating visibility of the context menu.
+ * - `position`: An object containing `x` and `y` coordinates for the context menu.
+ * - `setIsOpen` and `setPosition`: Functions to control the menu state and position.
+ *
+ * By default, the context menu is hidden, and its initial position is `{ x: 0, y: 0 }`.
+ * The hook automatically closes the menu when a click is detected anywhere on the document.
+ *
+ * @param {boolean} [initialOpen=false] - Initial visibility of the context menu.
+ * @param {{ x: number; y: number }} [initialPosition={ x: 0, y: 0 }] - Initial position of the context menu.
+ * @returns {UseContextMenuReturn} Object containing `isOpen`, `position`, and handler functions.
+ *
+ * @example
+ * ```tsx
+ * const { isOpen, setIsOpen, position, setPosition, handleContextMenu } = useContextMenu();
+ * ```
+ *
+ * @public
+ */
+export function useContextMenu(
+ initialOpen: boolean = false,
+ initialPosition: { x: number; y: number } = { x: 0, y: 0 }
+): UseContextMenuReturn {
+ const [isOpen, setIsOpen] = useState(initialOpen);
+ const [position, setPosition] = useState<{ x: number; y: number }>(initialPosition);
+
+ useEffect(() => {
+ /** Hide the context menu on any outside click */
+ const handleClickOutside = () => setIsOpen(false);
+
+ document.addEventListener("click", handleClickOutside);
+ return () => {
+ document.removeEventListener("click", handleClickOutside);
+ };
+ }, []);
+
+ /**
+ * Opens the context menu at the cursor's position on right-click.
+ * @param {MouseEvent} event - Mouse event triggered by right-click.
+ */
+ const handleContextMenu = (event: MouseEvent) => {
+ event.preventDefault();
+ setPosition({ x: event.clientX + 2, y: event.clientY - 6 });
+ setIsOpen(true);
+ };
+
+ return {
+ isOpen,
+ setIsOpen,
+ position,
+ setPosition,
+ handleContextMenu,
+ };
+}