fix: context menu backdrop blocks card onClick on close

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
EENE Dashboard
2026-06-01 12:00:29 +09:00
parent 4142d04361
commit 495a535d17

View File

@@ -1,4 +1,3 @@
import { useEffect, useRef } from 'react';
interface MenuItem {
label: string;
@@ -15,40 +14,42 @@ interface ContextMenuProps {
}
export function ContextMenu({ x, y, items, onClose }: ContextMenuProps) {
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
const close = (e: MouseEvent) => {
if (ref.current && !ref.current.contains(e.target as Node)) onClose();
};
document.addEventListener('mousedown', close);
return () => document.removeEventListener('mousedown', close);
}, [onClose]);
const adjustedY = Math.min(y, window.innerHeight - items.length * 46 - 20);
const adjustedX = Math.min(x, window.innerWidth - 170);
return (
<div
ref={ref}
style={{ position: 'fixed', top: adjustedY, left: adjustedX, zIndex: 9999 }}
className="bg-white rounded-xl shadow-2xl border border-gray-100 py-1.5 min-w-[155px]"
onContextMenu={(e) => e.preventDefault()}
>
{items.map((item, i) => (
<button
key={i}
onClick={() => { item.onClick(); onClose(); }}
className={`w-full text-left px-4 py-2.5 text-base font-semibold flex items-center gap-2.5 transition-colors ${
item.danger
? 'text-red-600 hover:bg-red-50'
: 'text-gray-700 hover:bg-gray-50'
}`}
>
<span className="text-lg leading-none">{item.icon}</span>
{item.label}
</button>
))}
</div>
<>
{/* 전체 화면 backdrop: mousedown을 잡아 카드 onClick이 발화하지 않도록 막음 */}
<div
className="fixed inset-0"
style={{ zIndex: 9998 }}
onMouseDown={(e) => {
e.stopPropagation();
onClose();
}}
onClick={(e) => e.stopPropagation()}
/>
<div
style={{ position: 'fixed', top: adjustedY, left: adjustedX, zIndex: 9999 }}
className="bg-white rounded-xl shadow-2xl border border-gray-100 py-1.5 min-w-[155px]"
onMouseDown={(e) => e.stopPropagation()}
onContextMenu={(e) => e.preventDefault()}
>
{items.map((item, i) => (
<button
key={i}
onClick={() => { item.onClick(); onClose(); }}
className={`w-full text-left px-4 py-2.5 text-base font-semibold flex items-center gap-2.5 transition-colors ${
item.danger
? 'text-red-600 hover:bg-red-50'
: 'text-gray-700 hover:bg-gray-50'
}`}
>
<span className="text-lg leading-none">{item.icon}</span>
{item.label}
</button>
))}
</div>
</>
);
}