mirror of https://github.com/coder/coder.git
168 lines
4.4 KiB
TypeScript
168 lines
4.4 KiB
TypeScript
import type { Interpolation, Theme } from "@emotion/react";
|
|
import LoadingButton, { type LoadingButtonProps } from "@mui/lab/LoadingButton";
|
|
import MuiDialog, {
|
|
type DialogProps as MuiDialogProps,
|
|
} from "@mui/material/Dialog";
|
|
import type { FC, ReactNode } from "react";
|
|
import type { ConfirmDialogType } from "./types";
|
|
|
|
export interface DialogActionButtonsProps {
|
|
/** Text to display in the cancel button */
|
|
cancelText?: string;
|
|
/** Text to display in the confirm button */
|
|
confirmText?: ReactNode;
|
|
/** Whether or not confirm is loading, also disables cancel when true */
|
|
confirmLoading?: boolean;
|
|
/** Whether or not the submit button is disabled */
|
|
disabled?: boolean;
|
|
/** Called when cancel is clicked */
|
|
onCancel?: () => void;
|
|
/** Called when confirm is clicked */
|
|
onConfirm?: () => void;
|
|
type?: ConfirmDialogType;
|
|
}
|
|
|
|
const typeToColor = (type: ConfirmDialogType): LoadingButtonProps["color"] => {
|
|
if (type === "delete") {
|
|
return "secondary";
|
|
}
|
|
return "primary";
|
|
};
|
|
|
|
/**
|
|
* Quickly handles most modals actions, some combination of a cancel and confirm button
|
|
*/
|
|
export const DialogActionButtons: FC<DialogActionButtonsProps> = ({
|
|
cancelText = "Cancel",
|
|
confirmText = "Confirm",
|
|
confirmLoading = false,
|
|
disabled = false,
|
|
onCancel,
|
|
onConfirm,
|
|
type = "info",
|
|
}) => {
|
|
return (
|
|
<>
|
|
{onCancel && (
|
|
<LoadingButton disabled={confirmLoading} onClick={onCancel} fullWidth>
|
|
{cancelText}
|
|
</LoadingButton>
|
|
)}
|
|
|
|
{onConfirm && (
|
|
<LoadingButton
|
|
fullWidth
|
|
data-testid="confirm-button"
|
|
variant="contained"
|
|
onClick={onConfirm}
|
|
color={typeToColor(type)}
|
|
loading={confirmLoading}
|
|
disabled={disabled}
|
|
type="submit"
|
|
css={[
|
|
type === "delete" && styles.dangerButton,
|
|
type === "success" && styles.successButton,
|
|
]}
|
|
>
|
|
{confirmText}
|
|
</LoadingButton>
|
|
)}
|
|
</>
|
|
);
|
|
};
|
|
|
|
const styles = {
|
|
dangerButton: (theme) => ({
|
|
"&.MuiButton-contained": {
|
|
backgroundColor: theme.roles.danger.fill.solid,
|
|
borderColor: theme.roles.danger.fill.outline,
|
|
|
|
"&:not(.MuiLoadingButton-loading)": {
|
|
color: theme.roles.danger.fill.text,
|
|
},
|
|
|
|
"&:hover:not(:disabled)": {
|
|
backgroundColor: theme.roles.danger.hover.fill.solid,
|
|
borderColor: theme.roles.danger.hover.fill.outline,
|
|
},
|
|
|
|
"&.Mui-disabled": {
|
|
backgroundColor: theme.roles.danger.disabled.background,
|
|
borderColor: theme.roles.danger.disabled.outline,
|
|
|
|
"&:not(.MuiLoadingButton-loading)": {
|
|
color: theme.roles.danger.disabled.fill.text,
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
successButton: (theme) => ({
|
|
"&.MuiButton-contained": {
|
|
backgroundColor: theme.palette.success.dark,
|
|
|
|
"&:not(.MuiLoadingButton-loading)": {
|
|
color: theme.palette.primary.contrastText,
|
|
},
|
|
|
|
"&:hover": {
|
|
backgroundColor: theme.palette.success.main,
|
|
|
|
"@media (hover: none)": {
|
|
backgroundColor: "transparent",
|
|
},
|
|
|
|
"&.Mui-disabled": {
|
|
backgroundColor: "transparent",
|
|
},
|
|
},
|
|
|
|
"&.Mui-disabled": {
|
|
backgroundColor: theme.palette.success.dark,
|
|
|
|
"&:not(.MuiLoadingButton-loading)": {
|
|
color: theme.palette.text.secondary,
|
|
},
|
|
},
|
|
},
|
|
|
|
"&.MuiButton-outlined": {
|
|
color: theme.palette.success.main,
|
|
borderColor: theme.palette.success.main,
|
|
"&:hover": {
|
|
backgroundColor: theme.palette.success.dark,
|
|
"@media (hover: none)": {
|
|
backgroundColor: "transparent",
|
|
},
|
|
"&.Mui-disabled": {
|
|
backgroundColor: "transparent",
|
|
},
|
|
},
|
|
"&.Mui-disabled": {
|
|
color: theme.palette.text.secondary,
|
|
borderColor: theme.palette.action.disabled,
|
|
},
|
|
},
|
|
|
|
"&.MuiButton-text": {
|
|
color: theme.palette.success.main,
|
|
"&:hover": {
|
|
backgroundColor: theme.palette.success.dark,
|
|
"@media (hover: none)": {
|
|
backgroundColor: "transparent",
|
|
},
|
|
},
|
|
"&.Mui-disabled": {
|
|
color: theme.palette.text.secondary,
|
|
},
|
|
},
|
|
}),
|
|
} satisfies Record<string, Interpolation<Theme>>;
|
|
|
|
export type DialogProps = MuiDialogProps;
|
|
|
|
/**
|
|
* Re-export of MUI's Dialog component, for convenience.
|
|
* @link See original documentation here: https://mui.com/material-ui/react-dialog/
|
|
*/
|
|
export { MuiDialog as Dialog };
|