mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: Update success confirmation dialog and snackbar (#2005)
* feat: update success confirmation dialog and snackbar * add success variants to confirm dialog and snackbar * update story name * use success variant for snackbar
This commit is contained in:
@@ -36,3 +36,24 @@ InfoDialog.args = {
|
||||
hideCancel: true,
|
||||
type: "info",
|
||||
}
|
||||
|
||||
export const InfoDialogWithCancel = Template.bind({})
|
||||
InfoDialogWithCancel.args = {
|
||||
description: "Information can be cool!",
|
||||
hideCancel: false,
|
||||
type: "info",
|
||||
}
|
||||
|
||||
export const SuccessDialog = Template.bind({})
|
||||
SuccessDialog.args = {
|
||||
description: "I am successful.",
|
||||
hideCancel: true,
|
||||
type: "success",
|
||||
}
|
||||
|
||||
export const SuccessDialogWithCancel = Template.bind({})
|
||||
SuccessDialogWithCancel.args = {
|
||||
description: "I may be successful.",
|
||||
hideCancel: false,
|
||||
type: "success",
|
||||
}
|
||||
|
||||
@@ -19,6 +19,10 @@ const CONFIRM_DIALOG_DEFAULTS: Record<ConfirmDialogType, ConfirmDialogTypeConfig
|
||||
confirmText: "OK",
|
||||
hideCancel: true,
|
||||
},
|
||||
success: {
|
||||
confirmText: "OK",
|
||||
hideCancel: true,
|
||||
},
|
||||
}
|
||||
|
||||
export interface ConfirmDialogProps extends Omit<DialogActionButtonsProps, "color" | "confirmDialog" | "onCancel"> {
|
||||
@@ -41,40 +45,32 @@ export interface ConfirmDialogProps extends Omit<DialogActionButtonsProps, "colo
|
||||
readonly title: string
|
||||
}
|
||||
|
||||
interface StyleProps {
|
||||
type: ConfirmDialogType
|
||||
}
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
dialogWrapper: (props: StyleProps) => ({
|
||||
dialogWrapper: {
|
||||
"& .MuiPaper-root": {
|
||||
background: props.type === "info" ? theme.palette.primary.main : theme.palette.background.paper,
|
||||
background: theme.palette.background.paper,
|
||||
border: `1px solid ${theme.palette.divider}`,
|
||||
},
|
||||
"& .MuiDialogActions-spacing": {
|
||||
padding: `0 ${theme.spacing(3.75)}px ${theme.spacing(3.75)}px`,
|
||||
},
|
||||
}),
|
||||
dialogContent: (props: StyleProps) => ({
|
||||
color: props.type === "info" ? theme.palette.primary.contrastText : theme.palette.text.secondary,
|
||||
},
|
||||
dialogContent: {
|
||||
color: theme.palette.text.secondary,
|
||||
padding: theme.spacing(6),
|
||||
textAlign: "center",
|
||||
}),
|
||||
},
|
||||
titleText: {
|
||||
marginBottom: theme.spacing(3),
|
||||
},
|
||||
description: (props: StyleProps) => ({
|
||||
color:
|
||||
props.type === "info" ? fade(theme.palette.primary.contrastText, 0.75) : fade(theme.palette.text.secondary, 0.75),
|
||||
description: {
|
||||
color: fade(theme.palette.text.secondary, 0.75),
|
||||
lineHeight: "160%",
|
||||
|
||||
"& strong": {
|
||||
color:
|
||||
props.type === "info"
|
||||
? fade(theme.palette.primary.contrastText, 0.95)
|
||||
: fade(theme.palette.text.secondary, 0.95),
|
||||
color: fade(theme.palette.text.secondary, 0.95),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}))
|
||||
|
||||
/**
|
||||
|
||||
@@ -126,11 +126,12 @@ export const DialogActionButtons: React.FC<DialogActionButtonsProps> = ({
|
||||
color={typeToColor(type)}
|
||||
loading={confirmLoading}
|
||||
type="submit"
|
||||
className={combineClasses([
|
||||
styles.dialogButton,
|
||||
styles.submitButton,
|
||||
type === "delete" ? styles.errorButton : "",
|
||||
])}
|
||||
className={combineClasses({
|
||||
[styles.dialogButton]: true,
|
||||
[styles.submitButton]: true,
|
||||
[styles.errorButton]: type === "delete",
|
||||
[styles.successButton]: type === "success",
|
||||
})}
|
||||
>
|
||||
{confirmText}
|
||||
</LoadingButton>
|
||||
@@ -246,6 +247,56 @@ const useButtonStyles = makeStyles((theme) => ({
|
||||
},
|
||||
},
|
||||
},
|
||||
successButton: {
|
||||
"&.MuiButton-contained": {
|
||||
backgroundColor: theme.palette.success.main,
|
||||
color: theme.palette.primary.contrastText,
|
||||
"&:hover": {
|
||||
backgroundColor: darken(theme.palette.success.main, 0.3),
|
||||
"@media (hover: none)": {
|
||||
backgroundColor: "transparent",
|
||||
},
|
||||
"&.Mui-disabled": {
|
||||
backgroundColor: "transparent",
|
||||
},
|
||||
},
|
||||
"&.Mui-disabled": {
|
||||
backgroundColor: theme.palette.action.disabledBackground,
|
||||
color: fade(theme.palette.text.disabled, 0.5),
|
||||
},
|
||||
},
|
||||
|
||||
"&.MuiButton-outlined": {
|
||||
color: theme.palette.success.main,
|
||||
borderColor: theme.palette.success.main,
|
||||
"&:hover": {
|
||||
backgroundColor: fade(theme.palette.success.main, theme.palette.action.hoverOpacity),
|
||||
"@media (hover: none)": {
|
||||
backgroundColor: "transparent",
|
||||
},
|
||||
"&.Mui-disabled": {
|
||||
backgroundColor: "transparent",
|
||||
},
|
||||
},
|
||||
"&.Mui-disabled": {
|
||||
color: fade(theme.palette.text.disabled, 0.5),
|
||||
borderColor: theme.palette.action.disabled,
|
||||
},
|
||||
},
|
||||
|
||||
"&.MuiButton-text": {
|
||||
color: theme.palette.success.main,
|
||||
"&:hover": {
|
||||
backgroundColor: fade(theme.palette.success.main, theme.palette.action.hoverOpacity),
|
||||
"@media (hover: none)": {
|
||||
backgroundColor: "transparent",
|
||||
},
|
||||
},
|
||||
"&.Mui-disabled": {
|
||||
color: fade(theme.palette.text.disabled, 0.5),
|
||||
},
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
export type DialogSearchProps = Omit<OutlinedInputProps, "className" | "fullWidth" | "labelWidth" | "startAdornment">
|
||||
|
||||
@@ -1 +1 @@
|
||||
export type ConfirmDialogType = "delete" | "info"
|
||||
export type ConfirmDialogType = "delete" | "info" | "success"
|
||||
|
||||
@@ -21,3 +21,10 @@ Info.args = {
|
||||
open: true,
|
||||
message: "Hey, something happened.",
|
||||
}
|
||||
|
||||
export const Success = Template.bind({})
|
||||
Success.args = {
|
||||
variant: "success",
|
||||
open: true,
|
||||
message: "Hey, something good happened.",
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import CloseIcon from "@material-ui/icons/Close"
|
||||
import { FC } from "react"
|
||||
import { combineClasses } from "../../util/combineClasses"
|
||||
|
||||
type EnterpriseSnackbarVariant = "error" | "info"
|
||||
type EnterpriseSnackbarVariant = "error" | "info" | "success"
|
||||
|
||||
export interface EnterpriseSnackbarProps extends MuiSnackbarProps {
|
||||
/** Called when the snackbar should close, either from timeout or clicking close */
|
||||
@@ -45,7 +45,7 @@ export const EnterpriseSnackbar: FC<EnterpriseSnackbarProps> = ({
|
||||
<div className={styles.actionWrapper}>
|
||||
{action}
|
||||
<IconButton onClick={onClose} className={styles.iconButton}>
|
||||
<CloseIcon className={variant === "info" ? styles.closeIcon : styles.closeIconError} />
|
||||
<CloseIcon className={styles.closeIcon} />
|
||||
</IconButton>
|
||||
</div>
|
||||
}
|
||||
@@ -55,6 +55,7 @@ export const EnterpriseSnackbar: FC<EnterpriseSnackbarProps> = ({
|
||||
[styles.snackbarContent]: true,
|
||||
[styles.snackbarContentInfo]: variant === "info",
|
||||
[styles.snackbarContentError]: variant === "error",
|
||||
[styles.snackbarContentSuccess]: variant === "success",
|
||||
}),
|
||||
}}
|
||||
onClose={onClose}
|
||||
@@ -73,12 +74,7 @@ const useStyles = makeStyles((theme) => ({
|
||||
closeIcon: {
|
||||
width: 25,
|
||||
height: 25,
|
||||
color: theme.palette.info.contrastText,
|
||||
},
|
||||
closeIconError: {
|
||||
width: 25,
|
||||
height: 25,
|
||||
color: theme.palette.error.contrastText,
|
||||
color: theme.palette.primary.contrastText,
|
||||
},
|
||||
snackbarContent: {
|
||||
border: `1px solid ${theme.palette.divider}`,
|
||||
@@ -87,16 +83,17 @@ const useStyles = makeStyles((theme) => ({
|
||||
padding: `${theme.spacing(1)}px ${theme.spacing(3)}px ${theme.spacing(1)}px ${theme.spacing(2)}px`,
|
||||
boxShadow: theme.shadows[6],
|
||||
alignItems: "inherit",
|
||||
},
|
||||
snackbarContentInfo: {
|
||||
backgroundColor: theme.palette.info.main,
|
||||
// Use primary color as a highlight
|
||||
borderLeftColor: theme.palette.primary.main,
|
||||
color: theme.palette.info.contrastText,
|
||||
},
|
||||
snackbarContentError: {
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
borderLeftColor: theme.palette.error.main,
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
snackbarContentInfo: {
|
||||
// Use success color as a highlight
|
||||
borderLeftColor: theme.palette.primary.main,
|
||||
},
|
||||
snackbarContentError: {
|
||||
borderLeftColor: theme.palette.error.main,
|
||||
},
|
||||
snackbarContentSuccess: {
|
||||
borderLeftColor: theme.palette.success.main,
|
||||
},
|
||||
}))
|
||||
|
||||
@@ -15,6 +15,16 @@ import {
|
||||
SnackbarEventType,
|
||||
} from "./utils"
|
||||
|
||||
const variantFromMsgType = (type: MsgType) => {
|
||||
if (type === MsgType.Error) {
|
||||
return "error"
|
||||
} else if (type === MsgType.Success) {
|
||||
return "success"
|
||||
} else {
|
||||
return "info"
|
||||
}
|
||||
}
|
||||
|
||||
export const GlobalSnackbar: React.FC = () => {
|
||||
const styles = useStyles()
|
||||
const [open, setOpen] = useState<boolean>(false)
|
||||
@@ -63,7 +73,7 @@ export const GlobalSnackbar: React.FC = () => {
|
||||
return (
|
||||
<EnterpriseSnackbar
|
||||
open={open}
|
||||
variant={notification.msgType === MsgType.Error ? "error" : "info"}
|
||||
variant={variantFromMsgType(notification.msgType)}
|
||||
message={
|
||||
<div className={styles.messageWrapper}>
|
||||
{notification.msgType === MsgType.Error && <ErrorIcon className={styles.errorIcon} />}
|
||||
|
||||
Reference in New Issue
Block a user