fleet/frontend/components/TableContainer/DataTable/ActionButton/ActionButton.tsx
Ian Littman f829170923
Update to TypeScript 6.0 (#43141)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.

## Testing

- [ ] QA'd all new/changed functionality manually
2026-04-09 08:28:59 -05:00

121 lines
3.2 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 resolvedButtonText =
typeof buttonText === "function" ? buttonText(targetIds) : buttonText;
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} />
)}
{resolvedButtonText}
{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;