Files
helm-dashboard/frontend/src/components/common/DropDown.tsx
T
yuri-sakharov c9b8fb7809 Introduced tsconfig.app.json and tsconfig.base.json + Refactored eslint.config.js to the latest structure (#652)
* Introduced tsconfig.app.json and tsconfig.base.json

* yarn.lock

* Introduced tsconfig.app.json, tsconfig.base.jsonfig.

* Refactored eslint.config.js to latest structure

* Returned previous recommended rules.

* More rules

* Force import rules

* Check

* Check

* Cleanup ESLint configuration and plugins

* Cleanup heap: "writable",DD_RUM: "writable" from ESLint configuration

* "scripts" moved to the top of package.json
2026-02-15 17:41:04 +00:00

109 lines
2.8 KiB
TypeScript

import { type ReactNode, Fragment, useEffect, useRef, useState } from "react";
import ArrowDownIcon from "../../assets/arrow-down-icon.svg";
export type DropDownItem = {
id: string;
text?: string;
icon?: ReactNode;
onClick?: () => void;
isSeparator?: boolean;
isDisabled?: boolean;
};
export type DropDownProps = {
items: DropDownItem[];
};
type PopupState = {
isOpen: boolean;
X: number;
Y: number;
};
function DropDown({ items }: DropDownProps) {
const [popupState, setPopupState] = useState<PopupState>({
isOpen: false,
X: 0,
Y: 0,
});
const modalRef = useRef<HTMLDivElement>(null);
const handleClickOutside = (event: MouseEvent) => {
if (modalRef.current && !modalRef.current.contains(event.target as Node)) {
setPopupState((prev) => ({
...prev,
isOpen: false,
}));
}
};
useEffect(() => {
if (popupState.isOpen) {
document.addEventListener("mousedown", handleClickOutside);
} else {
document.removeEventListener("mousedown", handleClickOutside);
}
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [popupState.isOpen]);
return (
<>
<div className="relative flex flex-col items-center">
<button
onClick={(e) => {
setPopupState((prev) => ({
...prev,
isOpen: !prev.isOpen,
X: e.pageX,
Y: e.pageY,
}));
}}
className="flex cursor-pointer items-center justify-between"
>
Help
<img src={ArrowDownIcon} className="ml-2 h-[10px] w-[10px]" />
</button>
</div>
{popupState.isOpen && (
<div
ref={modalRef}
className={`absolute z-10 mt-3 flex flex-col gap-1 rounded-sm border bg-white py-1 top-[${popupState.Y}] left-[${popupState.X}] border-gray-200`}
>
{items.map((item) => (
<Fragment key={item.id}>
{item.isSeparator ? (
<div className="h-[1px] bg-gray-300" />
) : (
<div
onClick={() => {
item.onClick?.();
setPopupState((prev) => ({
...prev,
isOpen: false,
}));
}}
className={`flex cursor-pointer items-center gap-2 py-1 pr-7 pl-3 font-normal hover:bg-dropdown ${
item.isDisabled
? "cursor-default text-gray-400 hover:bg-transparent"
: ""
}`}
>
{item.icon && <span> {item.icon ?? null}</span>}
<span>{item.text}</span>
</div>
)}
</Fragment>
))}
</div>
)}
</>
);
}
export default DropDown;