75 lines
2.0 KiB
TypeScript
75 lines
2.0 KiB
TypeScript
import { useState, useRef, useEffect } from "react";
|
|
import Button from "./Button";
|
|
import MoreIcon from "../icons/MoreIcon";
|
|
import PopoverWrapper from "./PopoverWrapper";
|
|
import clsx from "clsx";
|
|
import { useClickAway } from "@uidotdev/usehooks";
|
|
|
|
interface ActionsPopoverProps {
|
|
options: {
|
|
label: string;
|
|
onClick: () => void;
|
|
icon?: React.ReactNode;
|
|
disabled?: boolean;
|
|
}[];
|
|
isOpened?: boolean;
|
|
className?: string;
|
|
}
|
|
|
|
export default function ActionsPopover({
|
|
options,
|
|
isOpened = false,
|
|
className,
|
|
}: ActionsPopoverProps) {
|
|
const [opened, setOpened] = useState(isOpened);
|
|
|
|
const buttonRef = useRef<HTMLButtonElement>(null);
|
|
|
|
const ref = useClickAway<HTMLDivElement>(() => setOpened(false));
|
|
|
|
useEffect(() => {
|
|
const handleScroll = () => setOpened(false);
|
|
|
|
addEventListener("scroll", handleScroll, true);
|
|
|
|
return () => removeEventListener("scroll", handleScroll, true);
|
|
}, []);
|
|
|
|
return (
|
|
<div ref={ref} className="max-sm:max-h-6">
|
|
<button
|
|
ref={buttonRef}
|
|
className={clsx(
|
|
"2xl:rounded-[0.556vw] rounded-lg 2xl:p-[0.278vw] p-1 text-[#CCCCCC] 2xl:hover:text-[#7D7D7D] 2xl:hover:bg-[#F3F3F3] active:text-[#141414]",
|
|
opened && "max-sm:bg-[#F3F3F3]"
|
|
)}
|
|
onClick={() => setOpened(!opened)}
|
|
>
|
|
<div className="2xl:size-[1.111vw] size-4">
|
|
<MoreIcon />
|
|
</div>
|
|
</button>
|
|
|
|
<PopoverWrapper
|
|
isOpened={opened}
|
|
parentElRef={buttonRef}
|
|
position="vertical"
|
|
className={clsx("2xl:w-[17.222vw] max-2xl:w-[192px]", className)}
|
|
>
|
|
{options.map((option) => (
|
|
<Button
|
|
variant="tertiary"
|
|
className="w-full !justify-start"
|
|
key={option.label}
|
|
onClick={option.onClick}
|
|
disabled={option.disabled}
|
|
>
|
|
<div className="2xl:size-[1.111vw] size-4">{option.icon}</div>
|
|
{option.label}
|
|
</Button>
|
|
))}
|
|
</PopoverWrapper>
|
|
</div>
|
|
);
|
|
}
|