From f5dfd52f6efece2f4cad227044ecf4dd66301bbc Mon Sep 17 00:00:00 2001 From: crupest Date: Sat, 26 Aug 2023 21:36:58 +0800 Subject: ... --- FrontEnd/src/components/menu/PopupMenu.tsx | 73 ++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 FrontEnd/src/components/menu/PopupMenu.tsx (limited to 'FrontEnd/src/components/menu/PopupMenu.tsx') diff --git a/FrontEnd/src/components/menu/PopupMenu.tsx b/FrontEnd/src/components/menu/PopupMenu.tsx new file mode 100644 index 00000000..23a67f79 --- /dev/null +++ b/FrontEnd/src/components/menu/PopupMenu.tsx @@ -0,0 +1,73 @@ +import { useState, CSSProperties, ReactNode } from "react"; +import classNames from "classnames"; +import { createPortal } from "react-dom"; +import { usePopper } from "react-popper"; + +import { useClickOutside } from "~src/utilities/hooks"; + +import Menu, { MenuItems } from "./Menu"; + +import { ThemeColor } from "../common"; + +import "./PopupMenu.css"; + +export interface PopupMenuProps { + color?: ThemeColor; + items: MenuItems; + children?: ReactNode; + containerClassName?: string; + containerStyle?: CSSProperties; +} + +export default function PopupMenu({ + color, + items, + children, + containerClassName, + containerStyle, +}: PopupMenuProps) { + const [show, setShow] = useState(false); + + const [referenceElement, setReferenceElement] = + useState(null); + const [popperElement, setPopperElement] = useState( + null, + ); + const { styles, attributes } = usePopper(referenceElement, popperElement); + + useClickOutside(popperElement, () => setShow(false), true); + + return ( +
setShow(true)} + > + {children} + {show && + createPortal( +
+ { + setShow(false); + }} + /> +
, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + document.getElementById("portal")!, + )} +
+ ); +} -- cgit v1.2.3