Move alert away from material ui, restyle toasts
This commit is contained in:
parent
8c817d442b
commit
bc1d670ee0
@ -80,6 +80,7 @@
|
|||||||
"@styled-icons/fluentui-system-regular": "10.47.0",
|
"@styled-icons/fluentui-system-regular": "10.47.0",
|
||||||
"@styled-icons/heroicons-outline": "10.47.0",
|
"@styled-icons/heroicons-outline": "10.47.0",
|
||||||
"@styled-icons/material": "10.47.0",
|
"@styled-icons/material": "10.47.0",
|
||||||
|
"@styled-icons/material-outlined": "10.47.0",
|
||||||
"@styled-icons/material-rounded": "10.47.0",
|
"@styled-icons/material-rounded": "10.47.0",
|
||||||
"@styled-icons/remix-editor": "10.46.0",
|
"@styled-icons/remix-editor": "10.46.0",
|
||||||
"@styled-icons/simple-icons": "10.46.0",
|
"@styled-icons/simple-icons": "10.46.0",
|
||||||
|
@ -1,14 +1,10 @@
|
|||||||
import Button from '@mui/material/Button';
|
|
||||||
import Dialog from '@mui/material/Dialog';
|
|
||||||
import DialogActions from '@mui/material/DialogActions';
|
|
||||||
import DialogContent from '@mui/material/DialogContent';
|
|
||||||
import DialogContentText from '@mui/material/DialogContentText';
|
|
||||||
import DialogTitle from '@mui/material/DialogTitle';
|
|
||||||
import React, { useCallback, useMemo, useState } from 'react';
|
import React, { useCallback, useMemo, useState } from 'react';
|
||||||
import { translate } from 'react-polyglot';
|
import { translate } from 'react-polyglot';
|
||||||
|
|
||||||
import AlertEvent from '@staticcms/core/lib/util/events/AlertEvent';
|
import AlertEvent from '@staticcms/core/lib/util/events/AlertEvent';
|
||||||
import { useWindowEvent } from '@staticcms/core/lib/util/window.util';
|
import { useWindowEvent } from '@staticcms/core/lib/util/window.util';
|
||||||
|
import Button from '../button/Button';
|
||||||
|
import Modal from '../modal/Modal';
|
||||||
|
|
||||||
import type { TranslateProps } from 'react-polyglot';
|
import type { TranslateProps } from 'react-polyglot';
|
||||||
|
|
||||||
@ -68,24 +64,51 @@ const AlertDialog = ({ t }: TranslateProps) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<Modal
|
||||||
<Dialog
|
open
|
||||||
open
|
onClose={handleClose}
|
||||||
onClose={handleClose}
|
className="
|
||||||
aria-labelledby="alert-dialog-title"
|
w-[50%]
|
||||||
aria-describedby="alert-dialog-description"
|
min-w-[300px]
|
||||||
|
max-w-[600px]
|
||||||
|
"
|
||||||
|
aria-labelledby="alert-dialog-title"
|
||||||
|
aria-describedby="alert-dialog-description"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="
|
||||||
|
px-6
|
||||||
|
py-4
|
||||||
|
text-xl
|
||||||
|
bold
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<DialogTitle id="alert-dialog-title">{title}</DialogTitle>
|
{title}
|
||||||
<DialogContent>
|
</div>
|
||||||
<DialogContentText id="alert-dialog-description">{body}</DialogContentText>
|
<div
|
||||||
</DialogContent>
|
className="
|
||||||
<DialogActions>
|
px-6
|
||||||
<Button onClick={handleClose} variant="contained" color={color}>
|
pb-4
|
||||||
{okay}
|
text-sm
|
||||||
</Button>
|
text-slate-500
|
||||||
</DialogActions>
|
dark:text-slate-400
|
||||||
</Dialog>
|
"
|
||||||
</div>
|
>
|
||||||
|
{body}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="
|
||||||
|
p-2
|
||||||
|
flex
|
||||||
|
justify-end
|
||||||
|
gap-2
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<Button onClick={handleClose} variant="contained" color={color}>
|
||||||
|
{okay}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -84,8 +84,9 @@ const ConfirmDialog = ({ t }: TranslateProps) => {
|
|||||||
open
|
open
|
||||||
onClose={handleCancel}
|
onClose={handleCancel}
|
||||||
className="
|
className="
|
||||||
w-[540px]
|
w-[50%]
|
||||||
|
min-w-[300px]
|
||||||
|
max-w-[600px]
|
||||||
"
|
"
|
||||||
aria-labelledby="confirm-dialog-title"
|
aria-labelledby="confirm-dialog-title"
|
||||||
aria-describedby="confirm-dialog-description"
|
aria-describedby="confirm-dialog-description"
|
||||||
|
137
packages/core/src/components/snackbar/SnackbarAlert.tsx
Normal file
137
packages/core/src/components/snackbar/SnackbarAlert.tsx
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
import { Info as InfoIcon } from '@styled-icons/material-outlined/Info';
|
||||||
|
import { Close as CloseIcon } from '@styled-icons/material/Close';
|
||||||
|
import { ErrorOutline as ErrorOutlineIcon } from '@styled-icons/material/ErrorOutline';
|
||||||
|
import { TaskAlt as TaskAltIcon } from '@styled-icons/material/TaskAlt';
|
||||||
|
import { WarningAmber as WarningAmberIcon } from '@styled-icons/material/WarningAmber';
|
||||||
|
import React, { forwardRef, useMemo } from 'react';
|
||||||
|
|
||||||
|
import classNames from '@staticcms/core/lib/util/classNames.util';
|
||||||
|
import IconButton from '../common/button/IconButton';
|
||||||
|
|
||||||
|
import type { TranslatedProps } from '@staticcms/core/interface';
|
||||||
|
import type { SnackbarMessage } from '@staticcms/core/store/slices/snackbars';
|
||||||
|
|
||||||
|
interface SnackbarAlertProps {
|
||||||
|
data: SnackbarMessage;
|
||||||
|
onClose: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SnackbarAlert = forwardRef<HTMLDivElement, TranslatedProps<SnackbarAlertProps>>(
|
||||||
|
({ data, onClose, t }, ref) => {
|
||||||
|
const { type, message } = data;
|
||||||
|
|
||||||
|
const renderedMessage = useMemo(() => {
|
||||||
|
if (typeof message === 'string') {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { key, options } = message;
|
||||||
|
return t(key, options);
|
||||||
|
}, [message, t]);
|
||||||
|
|
||||||
|
const icon = useMemo(() => {
|
||||||
|
switch (type) {
|
||||||
|
case 'error':
|
||||||
|
return <ErrorOutlineIcon className="w-4 h-4" />;
|
||||||
|
case 'success':
|
||||||
|
return <TaskAltIcon className="w-4 h-4" />;
|
||||||
|
case 'warning':
|
||||||
|
return <WarningAmberIcon className="w-4 h-4" />;
|
||||||
|
default:
|
||||||
|
return <InfoIcon className="w-4 h-4" />;
|
||||||
|
}
|
||||||
|
}, [type]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
id="toast-default"
|
||||||
|
className="
|
||||||
|
flex
|
||||||
|
items-center
|
||||||
|
w-full
|
||||||
|
max-w-xs
|
||||||
|
gap-3
|
||||||
|
py-2
|
||||||
|
px-2.5
|
||||||
|
text-gray-500
|
||||||
|
bg-white
|
||||||
|
rounded-lg
|
||||||
|
shadow
|
||||||
|
dark:text-gray-300
|
||||||
|
dark:bg-gray-800
|
||||||
|
dark:shadow-lg
|
||||||
|
"
|
||||||
|
role="alert"
|
||||||
|
ref={ref}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={classNames(
|
||||||
|
`
|
||||||
|
inline-flex
|
||||||
|
items-center
|
||||||
|
justify-center
|
||||||
|
flex-shrink-0
|
||||||
|
w-7
|
||||||
|
h-7
|
||||||
|
rounded-lg
|
||||||
|
`,
|
||||||
|
type === 'error' &&
|
||||||
|
`
|
||||||
|
bg-red-500
|
||||||
|
text-red-100
|
||||||
|
dark:bg-red-600
|
||||||
|
dark:text-red-200
|
||||||
|
`,
|
||||||
|
type === 'success' &&
|
||||||
|
`
|
||||||
|
bg-green-500
|
||||||
|
text-green-100
|
||||||
|
dark:bg-green-600
|
||||||
|
dark:text-green-200
|
||||||
|
`,
|
||||||
|
type === 'warning' &&
|
||||||
|
`
|
||||||
|
bg-yellow-500
|
||||||
|
text-yellow-100
|
||||||
|
dark:bg-yellow-600
|
||||||
|
dark:text-yellow-200
|
||||||
|
`,
|
||||||
|
type === 'info' &&
|
||||||
|
`
|
||||||
|
text-blue-500
|
||||||
|
bg-blue-100
|
||||||
|
dark:bg-blue-800
|
||||||
|
dark:text-blue-200
|
||||||
|
`,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{icon}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="
|
||||||
|
text-sm
|
||||||
|
font-normal
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{renderedMessage}
|
||||||
|
</div>
|
||||||
|
<IconButton
|
||||||
|
aria-label="Close"
|
||||||
|
variant="text"
|
||||||
|
color="secondary"
|
||||||
|
onClick={onClose}
|
||||||
|
className="
|
||||||
|
ml-2
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<span className="sr-only">Close</span>
|
||||||
|
<CloseIcon className="w-4 h-4" />
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
SnackbarAlert.displayName = 'SnackbarAlert';
|
||||||
|
|
||||||
|
export default SnackbarAlert;
|
@ -1,21 +1,16 @@
|
|||||||
import { Close as CloseIcon } from '@styled-icons/material/Close';
|
|
||||||
import Alert from '@mui/material/Alert';
|
|
||||||
import IconButton from '@mui/material/IconButton';
|
|
||||||
import Snackbar from '@mui/material/Snackbar';
|
import Snackbar from '@mui/material/Snackbar';
|
||||||
import React, { useCallback, useEffect, useState } from 'react';
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
import { translate } from 'react-polyglot';
|
import { translate } from 'react-polyglot';
|
||||||
|
|
||||||
import { useAppDispatch, useAppSelector } from '@staticcms/core/store/hooks';
|
import { useAppDispatch, useAppSelector } from '@staticcms/core/store/hooks';
|
||||||
import { removeSnackbarById, selectSnackbars } from '@staticcms/core/store/slices/snackbars';
|
import { removeSnackbarById, selectSnackbars } from '@staticcms/core/store/slices/snackbars';
|
||||||
|
import SnackbarAlert from './SnackbarAlert';
|
||||||
|
|
||||||
import type { TranslatedProps } from '@staticcms/core/interface';
|
|
||||||
import type { SnackbarMessage } from '@staticcms/core/store/slices/snackbars';
|
import type { SnackbarMessage } from '@staticcms/core/store/slices/snackbars';
|
||||||
import type { SyntheticEvent } from 'react';
|
import type { FC, SyntheticEvent } from 'react';
|
||||||
|
import type { TranslateProps } from 'react-polyglot';
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
const Snackbars: FC<TranslateProps> = ({ t }) => {
|
||||||
interface SnackbarsProps {}
|
|
||||||
|
|
||||||
const Snackbars = ({ t }: TranslatedProps<SnackbarsProps>) => {
|
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [messageInfo, setMessageInfo] = useState<SnackbarMessage | undefined>(undefined);
|
const [messageInfo, setMessageInfo] = useState<SnackbarMessage | undefined>(undefined);
|
||||||
|
|
||||||
@ -47,42 +42,17 @@ const Snackbars = ({ t }: TranslatedProps<SnackbarsProps>) => {
|
|||||||
setMessageInfo(undefined);
|
setMessageInfo(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderAlert = useCallback(
|
|
||||||
(data: SnackbarMessage) => {
|
|
||||||
const { type, message } = data;
|
|
||||||
|
|
||||||
let renderedMessage: string;
|
|
||||||
if (typeof message === 'string') {
|
|
||||||
renderedMessage = message;
|
|
||||||
} else {
|
|
||||||
const { key, options } = message;
|
|
||||||
renderedMessage = t(key, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Alert key="message" onClose={handleClose} severity={type} sx={{ width: '100%' }}>
|
|
||||||
{renderedMessage}
|
|
||||||
</Alert>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
[handleClose, t],
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Snackbar
|
<Snackbar
|
||||||
key={messageInfo ? messageInfo.id : undefined}
|
key={messageInfo ? messageInfo.id : undefined}
|
||||||
open={open}
|
open={open}
|
||||||
autoHideDuration={6000}
|
autoHideDuration={600000}
|
||||||
onClose={handleClose}
|
onClose={handleClose}
|
||||||
TransitionProps={{ onExited: handleExited }}
|
TransitionProps={{ onExited: handleExited }}
|
||||||
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
|
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
|
||||||
action={
|
className="test"
|
||||||
<IconButton aria-label="close" color="inherit" sx={{ p: 0.5 }} onClick={handleClose}>
|
|
||||||
<CloseIcon className="h-5 w-5" />
|
|
||||||
</IconButton>
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{messageInfo ? renderAlert(messageInfo) : undefined}
|
{messageInfo ? <SnackbarAlert data={messageInfo} onClose={handleClose} t={t} /> : undefined}
|
||||||
</Snackbar>
|
</Snackbar>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -170,8 +170,8 @@
|
|||||||
.btn-contained-success {
|
.btn-contained-success {
|
||||||
@apply border
|
@apply border
|
||||||
border-transparent
|
border-transparent
|
||||||
bg-green-700
|
bg-green-600
|
||||||
hover:bg-green-800
|
hover:bg-green-700
|
||||||
text-white
|
text-white
|
||||||
disabled:text-gray-50
|
disabled:text-gray-50
|
||||||
disabled:bg-gray-300/80
|
disabled:bg-gray-300/80
|
||||||
@ -219,8 +219,8 @@
|
|||||||
.btn-contained-error {
|
.btn-contained-error {
|
||||||
@apply border
|
@apply border
|
||||||
border-transparent
|
border-transparent
|
||||||
bg-red-700
|
bg-red-600
|
||||||
hover:bg-red-800
|
hover:bg-red-700
|
||||||
text-white
|
text-white
|
||||||
disabled:text-gray-50
|
disabled:text-gray-50
|
||||||
disabled:bg-gray-300/80
|
disabled:bg-gray-300/80
|
||||||
|
@ -3700,6 +3700,14 @@
|
|||||||
"@babel/runtime" "^7.20.7"
|
"@babel/runtime" "^7.20.7"
|
||||||
"@styled-icons/styled-icon" "^10.7.0"
|
"@styled-icons/styled-icon" "^10.7.0"
|
||||||
|
|
||||||
|
"@styled-icons/material-outlined@10.47.0":
|
||||||
|
version "10.47.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@styled-icons/material-outlined/-/material-outlined-10.47.0.tgz#d799a14c1cbbd4d730d046d9f791f108e907fd34"
|
||||||
|
integrity sha512-/QeDSGXlfRoIsgx4g4Hb//xhsucD4mJJsNPk/e1XzckxkNG+YHCIjbAHzDwxwNfSCJYcTDcOp2SZcoS7iyNGlw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.20.7"
|
||||||
|
"@styled-icons/styled-icon" "^10.7.0"
|
||||||
|
|
||||||
"@styled-icons/material-rounded@10.47.0":
|
"@styled-icons/material-rounded@10.47.0":
|
||||||
version "10.47.0"
|
version "10.47.0"
|
||||||
resolved "https://registry.yarnpkg.com/@styled-icons/material-rounded/-/material-rounded-10.47.0.tgz#c2a9e8277ba88949caffe08d42360d7aa45afaa8"
|
resolved "https://registry.yarnpkg.com/@styled-icons/material-rounded/-/material-rounded-10.47.0.tgz#c2a9e8277ba88949caffe08d42360d7aa45afaa8"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user