mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
refactor(site): Redesign dialogs (#6237)
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { action } from "@storybook/addon-actions"
|
||||
import { ComponentMeta, Story } from "@storybook/react"
|
||||
import { ConfirmDialog, ConfirmDialogProps } from "./ConfirmDialog"
|
||||
|
||||
@@ -7,9 +8,11 @@ export default {
|
||||
argTypes: {
|
||||
onClose: {
|
||||
action: "onClose",
|
||||
defaultValue: action("onClose"),
|
||||
},
|
||||
onConfirm: {
|
||||
action: "onConfirm",
|
||||
defaultValue: action("onConfirm"),
|
||||
},
|
||||
open: {
|
||||
control: "boolean",
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import DialogActions from "@material-ui/core/DialogActions"
|
||||
import { alpha, makeStyles } from "@material-ui/core/styles"
|
||||
import Typography from "@material-ui/core/Typography"
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import { ReactNode, FC, PropsWithChildren } from "react"
|
||||
import {
|
||||
Dialog,
|
||||
@@ -61,25 +60,35 @@ const useStyles = makeStyles((theme) => ({
|
||||
"& .MuiPaper-root": {
|
||||
background: theme.palette.background.paper,
|
||||
border: `1px solid ${theme.palette.divider}`,
|
||||
width: "100%",
|
||||
maxWidth: theme.spacing(55),
|
||||
},
|
||||
"& .MuiDialogActions-spacing": {
|
||||
padding: `0 ${theme.spacing(3.75)}px ${theme.spacing(3.75)}px`,
|
||||
padding: `0 ${theme.spacing(5)}px ${theme.spacing(5)}px`,
|
||||
},
|
||||
},
|
||||
dialogContent: {
|
||||
color: theme.palette.text.secondary,
|
||||
padding: theme.spacing(6),
|
||||
textAlign: "center",
|
||||
padding: theme.spacing(5),
|
||||
},
|
||||
titleText: {
|
||||
marginBottom: theme.spacing(3),
|
||||
dialogTitle: {
|
||||
margin: 0,
|
||||
marginBottom: theme.spacing(2),
|
||||
color: theme.palette.text.primary,
|
||||
fontWeight: 400,
|
||||
fontSize: theme.spacing(2.5),
|
||||
},
|
||||
description: {
|
||||
color: alpha(theme.palette.text.secondary, 0.75),
|
||||
dialogDescription: {
|
||||
color: theme.palette.text.secondary,
|
||||
lineHeight: "160%",
|
||||
fontSize: 16,
|
||||
|
||||
"& strong": {
|
||||
color: alpha(theme.palette.text.secondary, 0.95),
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
|
||||
"& p": {
|
||||
margin: theme.spacing(1, 0),
|
||||
},
|
||||
},
|
||||
}))
|
||||
@@ -110,25 +119,11 @@ export const ConfirmDialog: FC<PropsWithChildren<ConfirmDialogProps>> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
className={styles.dialogWrapper}
|
||||
maxWidth="sm"
|
||||
onClose={onClose}
|
||||
open={open}
|
||||
>
|
||||
<Dialog className={styles.dialogWrapper} onClose={onClose} open={open}>
|
||||
<div className={styles.dialogContent}>
|
||||
<Typography className={styles.titleText} variant="h3">
|
||||
{title}
|
||||
</Typography>
|
||||
|
||||
<h3 className={styles.dialogTitle}>{title}</h3>
|
||||
{description && (
|
||||
<Typography
|
||||
component={typeof description === "string" ? "p" : "div"}
|
||||
className={styles.description}
|
||||
variant="body2"
|
||||
>
|
||||
{description}
|
||||
</Typography>
|
||||
<div className={styles.dialogDescription}>{description}</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { action } from "@storybook/addon-actions"
|
||||
import { ComponentMeta, Story } from "@storybook/react"
|
||||
import { DeleteDialog, DeleteDialogProps } from "./DeleteDialog"
|
||||
|
||||
@@ -7,9 +8,11 @@ export default {
|
||||
argTypes: {
|
||||
onCancel: {
|
||||
action: "onClose",
|
||||
defaultValue: action("onClose"),
|
||||
},
|
||||
onConfirm: {
|
||||
action: "onConfirm",
|
||||
defaultValue: action("onConfirm"),
|
||||
},
|
||||
open: {
|
||||
control: "boolean",
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import FormHelperText from "@material-ui/core/FormHelperText"
|
||||
import makeStyles from "@material-ui/core/styles/makeStyles"
|
||||
import TextField from "@material-ui/core/TextField"
|
||||
import Typography from "@material-ui/core/Typography"
|
||||
import { Maybe } from "components/Conditionals/Maybe"
|
||||
import { Stack } from "components/Stack/Stack"
|
||||
import { ChangeEvent, useState, PropsWithChildren, FC } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { ConfirmDialog } from "../ConfirmDialog/ConfirmDialog"
|
||||
@@ -34,30 +31,33 @@ export const DeleteDialog: FC<PropsWithChildren<DeleteDialogProps>> = ({
|
||||
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
setNameValue(event.target.value)
|
||||
}
|
||||
const hasError = nameValue.length > 0 && !confirmed
|
||||
|
||||
const content = (
|
||||
<>
|
||||
<Typography>{t("deleteDialog.intro", { entity })}</Typography>
|
||||
<p>{t("deleteDialog.intro", { entity })}</p>
|
||||
<Maybe condition={info !== undefined}>
|
||||
<Typography className={styles.warning}>{info}</Typography>
|
||||
<p className={styles.warning}>{info}</p>
|
||||
</Maybe>
|
||||
<Typography>{t("deleteDialog.confirm", { entity })}</Typography>
|
||||
<Stack spacing={1}>
|
||||
<TextField
|
||||
name="confirmation"
|
||||
autoComplete="off"
|
||||
id="confirmation"
|
||||
placeholder={name}
|
||||
value={nameValue}
|
||||
onChange={handleChange}
|
||||
label={t("deleteDialog.confirmLabel", { entity })}
|
||||
/>
|
||||
<Maybe condition={nameValue.length > 0 && !confirmed}>
|
||||
<FormHelperText error>
|
||||
{t("deleteDialog.incorrectName", { entity })}
|
||||
</FormHelperText>
|
||||
</Maybe>
|
||||
</Stack>
|
||||
<p>{t("deleteDialog.confirm", { entity })}</p>
|
||||
|
||||
<TextField
|
||||
fullWidth
|
||||
InputLabelProps={{
|
||||
shrink: true,
|
||||
}}
|
||||
autoFocus
|
||||
className={styles.textField}
|
||||
name="confirmation"
|
||||
autoComplete="off"
|
||||
id="confirmation"
|
||||
placeholder={name}
|
||||
value={nameValue}
|
||||
onChange={handleChange}
|
||||
label={t("deleteDialog.confirmLabel", { entity })}
|
||||
error={hasError}
|
||||
helperText={hasError && t("deleteDialog.incorrectName", { entity })}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -80,4 +80,8 @@ const useStyles = makeStyles((theme) => ({
|
||||
warning: {
|
||||
color: theme.palette.warning.light,
|
||||
},
|
||||
|
||||
textField: {
|
||||
marginTop: theme.spacing(3),
|
||||
},
|
||||
}))
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import MuiDialog, {
|
||||
DialogProps as MuiDialogProps,
|
||||
} from "@material-ui/core/Dialog"
|
||||
import { alpha, darken, lighten, makeStyles } from "@material-ui/core/styles"
|
||||
import { alpha, darken, makeStyles } from "@material-ui/core/styles"
|
||||
import * as React from "react"
|
||||
import { colors } from "theme/colors"
|
||||
import { combineClasses } from "../../util/combineClasses"
|
||||
import {
|
||||
LoadingButton,
|
||||
@@ -42,7 +43,6 @@ export const DialogActionButtons: React.FC<DialogActionButtonsProps> = ({
|
||||
cancelText = "Cancel",
|
||||
confirmText = "Confirm",
|
||||
confirmLoading = false,
|
||||
confirmDialog,
|
||||
disabled = false,
|
||||
onCancel,
|
||||
onConfirm,
|
||||
@@ -54,20 +54,17 @@ export const DialogActionButtons: React.FC<DialogActionButtonsProps> = ({
|
||||
<>
|
||||
{onCancel && (
|
||||
<LoadingButton
|
||||
className={combineClasses({
|
||||
[styles.dialogButton]: true,
|
||||
[styles.cancelButton]: true,
|
||||
[styles.confirmDialogCancelButton]: confirmDialog,
|
||||
})}
|
||||
disabled={confirmLoading}
|
||||
onClick={onCancel}
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
>
|
||||
{cancelText}
|
||||
</LoadingButton>
|
||||
)}
|
||||
{onConfirm && (
|
||||
<LoadingButton
|
||||
fullWidth
|
||||
variant="contained"
|
||||
onClick={onConfirm}
|
||||
color={typeToColor(type)}
|
||||
@@ -75,8 +72,6 @@ export const DialogActionButtons: React.FC<DialogActionButtonsProps> = ({
|
||||
disabled={disabled}
|
||||
type="submit"
|
||||
className={combineClasses({
|
||||
[styles.dialogButton]: true,
|
||||
[styles.submitButton]: true,
|
||||
[styles.errorButton]: type === "delete",
|
||||
[styles.successButton]: type === "success",
|
||||
})}
|
||||
@@ -88,119 +83,17 @@ export const DialogActionButtons: React.FC<DialogActionButtonsProps> = ({
|
||||
)
|
||||
}
|
||||
|
||||
interface StyleProps {
|
||||
type: ConfirmDialogType
|
||||
}
|
||||
|
||||
const useButtonStyles = makeStyles((theme) => ({
|
||||
dialogButton: {
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
fontSize: theme.typography.h6.fontSize,
|
||||
fontWeight: theme.typography.h5.fontWeight,
|
||||
padding: `${theme.spacing(0.75)}px ${theme.spacing(2)}px`,
|
||||
width: "100%",
|
||||
boxShadow: "none",
|
||||
},
|
||||
cancelButton: {
|
||||
background: alpha(theme.palette.primary.main, 0.1),
|
||||
color: theme.palette.primary.main,
|
||||
|
||||
"&:hover": {
|
||||
background: alpha(theme.palette.primary.main, 0.3),
|
||||
},
|
||||
},
|
||||
confirmDialogCancelButton: (props: StyleProps) => {
|
||||
const color =
|
||||
props.type === "info"
|
||||
? theme.palette.primary.contrastText
|
||||
: theme.palette.error.contrastText
|
||||
return {
|
||||
background: alpha(color, 0.15),
|
||||
color,
|
||||
|
||||
"&:hover": {
|
||||
background: alpha(color, 0.3),
|
||||
},
|
||||
|
||||
"&.Mui-disabled": {
|
||||
background: alpha(color, 0.15),
|
||||
color: alpha(color, 0.5),
|
||||
},
|
||||
}
|
||||
},
|
||||
submitButton: {
|
||||
// Override disabled to keep background color, change loading spinner to contrast color
|
||||
"&.Mui-disabled": {
|
||||
"&.MuiButton-containedPrimary": {
|
||||
background: theme.palette.primary.dark,
|
||||
|
||||
"& .MuiCircularProgress-root": {
|
||||
color: theme.palette.primary.contrastText,
|
||||
},
|
||||
},
|
||||
|
||||
"&.CdrButton-error.MuiButton-contained": {
|
||||
background: darken(theme.palette.error.main, 0.3),
|
||||
|
||||
"& .MuiCircularProgress-root": {
|
||||
color: theme.palette.error.contrastText,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
errorButton: {
|
||||
"&.MuiButton-contained": {
|
||||
backgroundColor: lighten(theme.palette.error.dark, 0.15),
|
||||
color: theme.palette.error.contrastText,
|
||||
backgroundColor: colors.red[10],
|
||||
borderColor: colors.red[9],
|
||||
color: theme.palette.text.primary,
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.error.dark,
|
||||
"@media (hover: none)": {
|
||||
backgroundColor: "transparent",
|
||||
},
|
||||
"&.Mui-disabled": {
|
||||
backgroundColor: "transparent",
|
||||
},
|
||||
backgroundColor: colors.red[9],
|
||||
},
|
||||
"&.Mui-disabled": {
|
||||
backgroundColor: theme.palette.action.disabledBackground,
|
||||
color: alpha(theme.palette.text.disabled, 0.5),
|
||||
},
|
||||
},
|
||||
|
||||
"&.MuiButton-outlined": {
|
||||
color: theme.palette.error.main,
|
||||
borderColor: theme.palette.error.main,
|
||||
"&:hover": {
|
||||
backgroundColor: alpha(
|
||||
theme.palette.error.main,
|
||||
theme.palette.action.hoverOpacity,
|
||||
),
|
||||
"@media (hover: none)": {
|
||||
backgroundColor: "transparent",
|
||||
},
|
||||
"&.Mui-disabled": {
|
||||
backgroundColor: "transparent",
|
||||
},
|
||||
},
|
||||
"&.Mui-disabled": {
|
||||
color: alpha(theme.palette.text.disabled, 0.5),
|
||||
borderColor: theme.palette.action.disabled,
|
||||
},
|
||||
},
|
||||
|
||||
"&.MuiButton-text": {
|
||||
color: theme.palette.error.main,
|
||||
"&:hover": {
|
||||
backgroundColor: alpha(
|
||||
theme.palette.error.main,
|
||||
theme.palette.action.hoverOpacity,
|
||||
),
|
||||
"@media (hover: none)": {
|
||||
backgroundColor: "transparent",
|
||||
},
|
||||
},
|
||||
"&.Mui-disabled": {
|
||||
color: alpha(theme.palette.text.disabled, 0.5),
|
||||
opacity: 0.5,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { action } from "@storybook/addon-actions"
|
||||
import { Story } from "@storybook/react"
|
||||
import { MockUser } from "../../../testHelpers/renderHelpers"
|
||||
import {
|
||||
@@ -9,8 +10,8 @@ export default {
|
||||
title: "components/Dialogs/ResetPasswordDialog",
|
||||
component: ResetPasswordDialog,
|
||||
argTypes: {
|
||||
onClose: { action: "onClose" },
|
||||
onConfirm: { action: "onConfirm" },
|
||||
onClose: { action: "onClose", defaultValue: action("onClose") },
|
||||
onConfirm: { action: "onConfirm", defaultValue: action("onConfirm") },
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import DialogContentText from "@material-ui/core/DialogContentText"
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import { FC } from "react"
|
||||
import * as TypesGen from "../../../api/typesGenerated"
|
||||
@@ -31,12 +30,8 @@ export const ResetPasswordDialog: FC<
|
||||
|
||||
const description = (
|
||||
<>
|
||||
<DialogContentText variant="subtitle2">
|
||||
{Language.message(user?.username)}
|
||||
</DialogContentText>
|
||||
<DialogContentText component="div" className={styles.codeBlock}>
|
||||
<CodeExample code={newPassword ?? ""} className={styles.codeExample} />
|
||||
</DialogContentText>
|
||||
<p>{Language.message(user?.username)}</p>
|
||||
<CodeExample code={newPassword ?? ""} className={styles.codeExample} />
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -55,13 +50,11 @@ export const ResetPasswordDialog: FC<
|
||||
)
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
codeBlock: {
|
||||
marginBottom: 0,
|
||||
},
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
codeExample: {
|
||||
minHeight: "auto",
|
||||
userSelect: "all",
|
||||
width: "100%",
|
||||
marginTop: theme.spacing(3),
|
||||
},
|
||||
}))
|
||||
|
||||
Reference in New Issue
Block a user