fleet/frontend/components/TableContainer/DataTable/ActionButton/ActionButton.tsx

119 lines
3.1 KiB
TypeScript

import React, { useCallback } from "react";
import { kebabCase, noop } from "lodash";
import classnames from "classnames";
import { ButtonVariant } from "components/buttons/Button/Button";
import Icon from "components/Icon/Icon";
import { IconNames } from "components/icons";
import TooltipWrapper from "components/TooltipWrapper";
import { Colors } from "styles/var/colors";
import Button from "../../../buttons/Button";
const baseClass = "action-button";
export interface IActionButtonProps {
name: string;
buttonText: string | ((targetIds: number[]) => string);
onClick?: (ids: number[]) => void;
targetIds?: number[]; // TODO figure out undefined case
variant?: ButtonVariant;
hideButton?: boolean | ((targetIds: number[]) => boolean);
iconSvg?: IconNames;
iconStroke?: boolean;
iconColor?: Colors;
iconPosition?: string;
isDisabled?: boolean;
tooltipContent?: React.ReactNode;
}
function useActionCallback(
callbackFn: (targetIds: number[]) => void | undefined
) {
return useCallback(
(targetIds: any) => {
callbackFn(targetIds);
},
[callbackFn]
);
}
const ActionButton = (buttonProps: IActionButtonProps): JSX.Element | null => {
const {
name,
buttonText,
onClick,
targetIds = [],
variant = "default",
hideButton,
iconSvg,
iconStroke = false,
iconColor,
iconPosition,
isDisabled,
tooltipContent,
} = buttonProps;
const onButtonClick = useActionCallback(onClick || noop);
// hideButton is intended to provide a flexible way to specify show/hide conditions via a boolean or a function that evaluates to a boolean
// currently it is typed to accept an array of targetIds but this typing could easily be expanded to include other use cases
const isHidden = (
hideButtonProp: boolean | ((ids: number[]) => boolean) | undefined
) => {
if (typeof hideButtonProp === "function") {
return hideButtonProp(targetIds);
}
return Boolean(hideButtonProp);
};
if (isHidden(hideButton)) {
return null;
}
const buttonClasses = classnames(
baseClass,
`${baseClass}__${kebabCase(name)}`,
{ [`${baseClass}__disabled`]: isDisabled }
);
const renderButton = () => (
<div className={buttonClasses}>
<Button
onClick={() => onButtonClick(targetIds)}
variant={variant}
iconStroke={iconStroke}
size="small"
>
<>
{iconPosition === "left" && iconSvg && (
<Icon name={iconSvg} color={iconColor} />
)}
{buttonText}
{iconPosition !== "left" && iconSvg && (
<Icon name={iconSvg} color={iconColor} />
)}
</>
</Button>
</div>
);
if (tooltipContent) {
return (
<div className={baseClass}>
<TooltipWrapper
tipContent={tooltipContent}
position="top"
fixedPositionStrategy
underline={false}
clickable={false}
showArrow
>
{renderButton()}
</TooltipWrapper>
</div>
);
}
return renderButton();
};
export default ActionButton;