Files
Checkmate/Client/src/Components/Alert/index.jsx
T

106 lines
3.0 KiB
React
Raw Normal View History

2024-07-06 14:44:04 -04:00
import PropTypes from "prop-types";
2024-07-06 14:33:36 -04:00
import { useTheme } from "@emotion/react";
2024-07-11 16:45:29 -04:00
import { Box, IconButton, Stack } from "@mui/material";
2024-07-06 14:33:36 -04:00
import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined";
import ErrorOutlineOutlinedIcon from "@mui/icons-material/ErrorOutlineOutlined";
import WarningAmberOutlinedIcon from "@mui/icons-material/WarningAmberOutlined";
2024-07-11 16:45:29 -04:00
import CloseIcon from "@mui/icons-material/Close";
2024-07-06 14:33:36 -04:00
import "./index.css";
2024-07-11 16:45:29 -04:00
import Button from "../Button";
2024-07-06 14:33:36 -04:00
2024-07-06 14:44:04 -04:00
/**
* Icons mapping for different alert variants.
* @type {Object<string, JSX.Element>}
*/
2024-07-06 14:33:36 -04:00
const icons = {
info: <InfoOutlinedIcon />,
error: <ErrorOutlineOutlinedIcon />,
warning: <WarningAmberOutlinedIcon />,
};
2024-07-06 14:44:04 -04:00
/**
* @param {Object} props
* @param {'info' | 'error' | 'warning'} props.variant - The type of alert.
* @param {string} [props.title] - The title of the alert.
* @param {string} [props.body] - The body text of the alert.
* @returns {JSX.Element}
*/
2024-07-11 16:45:29 -04:00
const Alert = ({ variant, title, body, toast, hasIcon = true, onClick }) => {
2024-07-06 14:33:36 -04:00
const theme = useTheme();
const { bg, border, color } = theme.alert[variant];
const icon = icons[variant];
return (
<Stack
direction="row"
justifyContent="flex-start"
2024-07-11 16:45:29 -04:00
alignItems={hasIcon ? "" : "center"}
2024-07-06 14:33:36 -04:00
className="alert row-stack"
gap={theme.gap.ml}
sx={{
2024-07-11 16:45:29 -04:00
padding: hasIcon ? theme.gap.ml : `${theme.gap.small} ${theme.gap.ml}`,
2024-07-06 14:33:36 -04:00
backgroundColor: bg,
border: `solid 1px ${border}`,
borderRadius: `${theme.shape.borderRadius}px`,
}}
>
2024-07-11 16:45:29 -04:00
{hasIcon && <Box sx={{ color: color }}>{icon}</Box>}
2024-07-06 14:33:36 -04:00
<Stack direction="column" gap="2px" sx={{ flex: 1, color: color }}>
{title && <Box sx={{ fontWeight: "700" }}>{title}</Box>}
{body && <Box sx={{ fontWeight: "400" }}>{body}</Box>}
2024-07-11 16:45:29 -04:00
{hasIcon && toast && (
<Button
level="tertiary"
label="Dismiss"
onClick={onClick}
sx={{
fontWeight: "600",
width: "fit-content",
mt: theme.gap.small,
padding: 0,
minWidth: 0,
"&:hover": {
backgroundColor: "transparent",
},
"& .MuiTouchRipple-root": {
pointerEvents: "none",
display: "none",
},
}}
></Button>
)}
2024-07-06 14:33:36 -04:00
</Stack>
2024-07-11 16:45:29 -04:00
{toast && (
<IconButton
onClick={onClick}
sx={{
alignSelf: "flex-start",
ml: "auto",
mr: "-5px",
mt: hasIcon ? "-5px" : 0,
padding: "5px",
"&:focus": {
outline: "none",
},
}}
>
<CloseIcon
sx={{
fontSize: "20px",
}}
/>
</IconButton>
)}
2024-07-06 14:33:36 -04:00
</Stack>
);
};
2024-07-06 14:44:04 -04:00
Alert.propTypes = {
variant: PropTypes.oneOf(["info", "error", "warning"]).isRequired,
title: PropTypes.string,
body: PropTypes.string,
};
2024-07-06 14:33:36 -04:00
export default Alert;