Files
infisical/frontend/src/components/v2/Menu/Menu.tsx
T
2025-10-13 14:52:38 -07:00

79 lines
2.3 KiB
TypeScript

import { ComponentPropsWithRef, ElementType, ReactNode, Ref } from "react";
import { twMerge } from "tailwind-merge";
export type MenuProps = {
children: ReactNode;
className?: string;
};
export const Menu = ({ children, className }: MenuProps): JSX.Element => {
return <ul className={twMerge("p-2", className)}>{children}</ul>;
};
export type MenuItemProps<T extends ElementType> = {
// Kudos to https://itnext.io/react-polymorphic-components-with-typescript-f7ce72ea7af2
as?: T;
children?: ReactNode;
leftIcon?: ReactNode;
description?: ReactNode;
isDisabled?: boolean;
isSelected?: boolean;
className?: string;
inputRef?: Ref<T>;
};
export const MenuItem = <T extends ElementType = "button">({
children,
leftIcon,
iconMode,
className,
isDisabled,
isSelected,
as: Item = "div",
description,
// wrapping in forward ref with generic component causes the loss of ts definitions on props
inputRef,
variant,
...props
}: MenuItemProps<T> &
ComponentPropsWithRef<T> & { variant?: "project" | "namespace" | "org" }): JSX.Element => {
return (
<Item
type="button"
role="menuitem"
className={twMerge(
"group relative mt-0.5 box-border flex w-full cursor-pointer items-center rounded-[2px] border-l-2 border-transparent px-2 py-2 font-inter text-sm text-bunker-100 transition-all duration-50 hover:bg-mineshaft-700",
isSelected && "bg-mineshaft-600 hover:bg-mineshaft-600",
isDisabled && "cursor-not-allowed hover:bg-transparent",
isSelected && variant === "org" && "border-org-v1",
isSelected && variant === "namespace" && "border-namespace-v1",
isSelected && variant === "project" && "border-primary",
className
)}
ref={inputRef}
{...props}
>
{leftIcon}
{children && <span className="grow text-left whitespace-nowrap">{children}</span>}
{description && <span className="mt-2 text-xs">{description}</span>}
</Item>
);
};
MenuItem.displayName = "MenuItem";
export type MenuGroupProps = {
children: ReactNode;
title: ReactNode;
className?: string;
};
export const MenuGroup = ({ children, title, className }: MenuGroupProps): JSX.Element => (
<>
<li className={twMerge("px-2 pt-3 text-xs font-medium text-gray-400 uppercase", className)}>
{title}
</li>
{children}
</>
);