plane/apps/app/components/ui/context-menu.tsx

104 lines
2.4 KiB
TypeScript
Raw Permalink Normal View History

import React, { useEffect } from "react";
import Link from "next/link";
type Props = {
position: {
x: number;
y: number;
};
children: React.ReactNode;
title?: string | JSX.Element;
isOpen: boolean;
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
};
const ContextMenu = ({ position, children, title, isOpen, setIsOpen }: Props) => {
useEffect(() => {
2023-03-05 14:52:01 +00:00
const hideContextMenu = () => {
if (isOpen) setIsOpen(false);
};
window.addEventListener("click", hideContextMenu);
2023-03-05 17:54:50 +00:00
window.addEventListener("keydown", (e: KeyboardEvent) => {
if (e.key === "Escape") hideContextMenu();
});
return () => {
window.removeEventListener("click", hideContextMenu);
2023-03-05 14:52:01 +00:00
window.removeEventListener("keydown", hideContextMenu);
};
}, [isOpen, setIsOpen]);
return (
<div
className={`fixed z-20 h-full w-full ${
isOpen ? "pointer-events-auto opacity-100" : "pointer-events-none opacity-0"
}`}
>
<div
className={`fixed z-20 flex min-w-[8rem] flex-col items-stretch gap-1 rounded-md border border-brand-base bg-brand-surface-1 p-2 text-xs shadow-lg`}
style={{
left: `${position.x}px`,
top: `${position.y}px`,
}}
>
{title && (
<h4 className="border-b border-brand-base px-1 py-1 pb-2 text-[0.8rem] font-medium">
{title}
</h4>
)}
{children}
</div>
</div>
);
};
type MenuItemProps = {
children: JSX.Element | string;
renderAs?: "button" | "a";
href?: string;
onClick?: () => void;
className?: string;
Icon?: any;
};
const MenuItem: React.FC<MenuItemProps> = ({
children,
renderAs,
href = "",
onClick,
className = "",
Icon,
}) => (
2023-03-05 14:52:01 +00:00
<>
{renderAs === "a" ? (
<Link href={href}>
2023-03-05 14:52:01 +00:00
<a
className={`${className} flex w-full items-center gap-2 rounded px-1 py-1.5 text-left text-brand-secondary hover:bg-brand-surface-2`}
2023-03-05 14:52:01 +00:00
>
<>
{Icon && <Icon />}
{children}
</>
</a>
</Link>
) : (
2023-03-05 14:52:01 +00:00
<button
type="button"
className={`${className} flex w-full items-center gap-2 rounded px-1 py-1.5 text-left text-brand-secondary hover:bg-brand-surface-2`}
2023-03-05 14:52:01 +00:00
onClick={onClick}
>
<>
{Icon && <Icon height={12} width={12} />}
{children}
</>
</button>
)}
2023-03-05 14:52:01 +00:00
</>
);
ContextMenu.Item = MenuItem;
export { ContextMenu };