Files
HiveGrid-Wireframes/hivegrid-cloud/apps/web/app/components/ui/dropdowns/MenuWithPopper.tsx
T

103 lines
4.0 KiB
TypeScript

import React, { MouseEventHandler, ReactNode } from "react";
import { Menu, Transition } from "@headlessui/react";
import clsx from "clsx";
import { usePopper } from "./use-popper";
import { Link } from "react-router";
interface Props {
button: ReactNode;
options: {
title?: string;
routePath?: string;
onClick?: () => void | undefined;
disabled?: boolean;
className?: string;
render?: (active: boolean, close: () => void) => ReactNode;
}[];
size?: "sm" | "md" | "lg" | "xl";
onClick?: MouseEventHandler<HTMLButtonElement>;
className?: string;
}
export default function MenuWithPopper({ button, options, size = "sm", onClick, className }: Props) {
let [trigger, container] = usePopper({
strategy: "fixed",
});
return (
<Menu>
<span>
<Menu.Button ref={trigger} onClick={onClick} className={className}>
{button}
</Menu.Button>
</span>
<div ref={container} className={clsx(size === "sm" && "w-56", size === "md" && "w-64", size === "lg" && "w-80", size === "xl" && "w-96")}>
<Transition
enter="transition duration-100 ease-out"
enterFrom="transform scale-95 opacity-0"
enterTo="transform scale-100 opacity-100"
leave="transition duration-75 ease-out"
leaveFrom="transform scale-100 opacity-100"
leaveTo="transform scale-95 opacity-0"
>
<Menu.Items className="border-border-default bg-surface-neutral-modal divide-border-default divide-y rounded-md border shadow-lg outline-hidden">
<div className="py-1">
{options.map((item, idx) => {
return (
<Menu.Item key={idx}>
{({ active, close }) => (
<>
{item.render && item.render(active, close)}
{item.onClick && (
<button
type="button"
className={clsx(
item.className,
"hover:bg-surface-neutral-secondary w-full text-left",
item.disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer",
active ? "text-text-neutral-primary bg-surface-neutral-secondary" : "text-text-neutral-secondary",
"block px-4 py-2 text-sm"
)}
disabled={item.disabled}
onClick={(e) => {
e.stopPropagation();
if (item.onClick) {
item.onClick();
}
close();
}}
>
{item.title}
</button>
)}
{item.routePath && (
<Link
to={item.routePath}
onClick={(e) => {
e.stopPropagation();
close();
}}
className={clsx(
item.className,
"hover:bg-surface-neutral-secondary w-full text-left",
item.disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer",
active ? "text-text-neutral-primary bg-surface-neutral-secondary" : "text-text-neutral-secondary",
"block px-4 py-2 text-sm"
)}
>
{item.title}
</Link>
)}
</>
)}
</Menu.Item>
);
})}
</div>
</Menu.Items>
</Transition>
</div>
</Menu>
);
}