Refactored components styling 2/2

This commit is contained in:
Daniel Cojocea
2024-08-27 17:01:28 -04:00
parent 8b27bc2ab2
commit edeaf2ede9
23 changed files with 481 additions and 459 deletions
+27 -11
View File
@@ -2,7 +2,7 @@ import "./check.css";
import PropTypes from "prop-types";
import CheckGrey from "../../assets/icons/check.svg?react";
import CheckOutlined from "../../assets/icons/check-outlined.svg?react";
import { Stack, Typography } from "@mui/material";
import { Box, Stack, Typography } from "@mui/material";
import { useTheme } from "@emotion/react";
/**
@@ -22,25 +22,41 @@ import { useTheme } from "@emotion/react";
*/
const Check = ({ text, variant = "info", outlined = false }) => {
const theme = useTheme();
const colors = {
success: theme.palette.success.main,
error: theme.palette.error.text,
info: theme.palette.info.border,
};
return (
<Stack
direction="row"
gap={outlined ? theme.gap.medium : theme.gap.small}
className={`check${
variant === "error"
? " check-error"
: variant === "success"
? " check-success"
: " check-info"
}`}
className="check"
gap={outlined ? theme.spacing(6) : theme.spacing(4)}
alignItems="center"
>
{outlined ? (
<CheckOutlined alt="check" />
) : (
<CheckGrey alt="form checks" />
<Box
lineHeight={0}
sx={{
"& svg > path": { fill: colors[variant] },
}}
>
<CheckGrey alt="form checks" />
</Box>
)}
<Typography component="span">{text}</Typography>
<Typography
component="span"
sx={{
color:
variant === "info" ? theme.palette.text.tertiary : colors[variant],
opacity: 0.8,
}}
>
{text}
</Typography>
</Stack>
);
};
+1 -17
View File
@@ -1,17 +1 @@
.check > span.MuiTypography-root {
font-size: var(--env-var-font-size-small-plus);
color: var(--secondary-color-light);
opacity: 0.8;
}
.check-error span.MuiTypography-root {
color: var(--error-color);
}
.check-error svg > path {
fill: var(--error-color);
}
.check-success span.MuiTypography-root {
color: var(--success-color);
}
.check-success svg > path {
fill: var(--success-color);
}
-4
View File
@@ -7,10 +7,6 @@
font-size: var(--env-var-font-size-large);
font-weight: 600;
}
[class*="fallback__"] .check span.MuiTypography-root,
[class*="fallback__"] h1.MuiTypography-root {
color: var(--secondary-color);
}
[class*="fallback__"] button.MuiButtonBase-root,
[class*="fallback__"] .check {
width: max-content;
+7 -3
View File
@@ -27,15 +27,19 @@ const Fallback = ({ title, checks, link = "/" }) => {
<Stack
className={`fallback__${title.trim().split(" ")[0]}`}
alignItems="center"
gap={theme.gap.xl}
gap={theme.spacing(20)}
>
<Skeleton style={{ zIndex: 1 }} />
<Box
className="background-pattern-svg"
sx={{ backgroundImage: `url(${background})` }}
/>
<Stack gap={theme.gap.small} maxWidth={"275px"} zIndex={1}>
<Typography component="h1" marginY={theme.gap.medium}>
<Stack gap={theme.spacing(4)} maxWidth={"275px"} zIndex={1}>
<Typography
component="h1"
marginY={theme.spacing(6)}
color={theme.palette.text.secondary}
>
A {title} is used to:
</Typography>
{checks.map((check, index) => (
@@ -1,14 +0,0 @@
.checkbox-wrapper {
border-radius: var(--env-var-radius-1);
}
.checkbox-wrapper:not(:has(.Mui-disabled)):hover {
background-color: var(--unresolved-bg);
}
.checkbox-wrapper span.MuiTypography-root {
font-size: var(--env-var-font-size-medium);
color: var(--secondary-color-light);
}
.checkbox-wrapper .MuiButtonBase-root {
margin-right: var(--env-var-spacing-1);
padding: 0;
}
@@ -1,5 +1,6 @@
import PropTypes from "prop-types";
import { FormControlLabel, Checkbox as MuiCheckbox } from "@mui/material";
import { useTheme } from "@emotion/react";
import CheckboxOutline from "../../../assets/icons/checkbox-outline.svg?react";
import CheckboxFilled from "../../../assets/icons/checkbox-filled.svg?react";
@@ -16,7 +17,7 @@ import "./index.css";
* @param {boolean} [props.isDisabled] - Whether the checkbox is disabled or not.
*
* @returns {JSX.Element}
*
*
* @example
* <Checkbox
* id="checkbox-id"
@@ -37,6 +38,7 @@ const Checkbox = ({
isDisabled,
}) => {
const sizes = { small: "14px", medium: "16px", large: "18px" };
const theme = useTheme();
return (
<FormControlLabel
@@ -61,10 +63,20 @@ const Checkbox = ({
label={label}
disabled={isDisabled}
sx={{
p: "5px",
m: "-5px",
borderRadius: theme.shape.borderRadius,
p: theme.spacing(2.5),
m: theme.spacing(-2.5),
"& .MuiButtonBase-root": {
width: "20px",
width: theme.spacing(10),
p: 0,
mr: theme.spacing(6),
},
"&:not(:has(.Mui-disabled)):hover": {
backgroundColor: theme.palette.unresolved.bg,
},
"& span.MuiTypography-root": {
fontSize: 13,
color: theme.palette.text.tertiary,
},
}}
/>
+1 -52
View File
@@ -8,24 +8,6 @@
.field .input-error {
font-size: var(--env-var-font-size-medium);
}
.field h3.MuiTypography-root,
.field h5.MuiTypography-root,
.field input,
.field textarea {
color: var(--secondary-color);
}
.field h3.MuiTypography-root {
font-weight: 500;
}
.field h3.MuiTypography-root span.field-required {
color: var(--error-color);
margin-left: 2px;
}
.field h3.MuiTypography-root span.field-optional {
opacity: 0.6;
margin-left: 4px;
font-weight: 400;
}
.field h5.MuiTypography-root {
position: relative;
opacity: 0.8;
@@ -37,24 +19,7 @@
.field .MuiInputBase-root:has(.MuiInputAdornment-root) {
padding-right: var(--env-var-spacing-1-minus);
}
.field
.MuiInputBase-root:has(.copy.MuiInputAdornment-root > .MuiButtonBase-root) {
padding-right: 0;
}
.field .MuiInputBase-root .copy.MuiInputAdornment-root .MuiButtonBase-root {
padding: 0 var(--env-var-spacing-1-minus);
font-size: var(--env-var-font-size-medium);
border-radius: 0;
height: 34px;
}
.field .MuiInputBase-root .copy.MuiInputAdornment-root .MuiButtonBase-root svg {
width: 20px;
height: 20px;
margin-right: 5px;
}
.field .MuiInputBase-root .MuiInputAdornment-root .MuiButtonBase-root:hover {
border-color: var(--border-color-dark);
}
.field input {
height: 100%;
padding: 0 var(--env-var-spacing-1-minus);
@@ -62,22 +27,6 @@
.field .MuiInputBase-root:has(textarea) {
padding: var(--env-var-spacing-1-minus);
}
.field .MuiOutlinedInput-root fieldset {
border-color: var(--border-color-dark);
border-radius: var(--env-var-radius-1);
}
.field:not(:has(.Mui-disabled)):not(:has(.input-error))
.MuiOutlinedInput-root:hover:not(:has(input:focus)):not(:has(textarea:focus))
fieldset {
border-color: var(--border-color-dark);
}
.field .input-error {
color: var(--error-color);
opacity: 0.8;
}
.field:has(.input-error) .MuiOutlinedInput-root fieldset {
border-color: var(--error-color);
}
.register-page .field .MuiOutlinedInput-root fieldset,
.register-page .field input,
+72 -58
View File
@@ -23,7 +23,6 @@ import { forwardRef, useState } from "react";
* @param {boolean} [props.isRequired] - Indicates if the field is required, will display a red asterisk.
* @param {boolean} [props.isOptional] - Indicates if the field is optional, will display optional text.
* @param {string} [props.optionalLabel] - Optional label for the input field.
* @param {boolean} [props.hasCopy] - Indicates if the field supports copying.
* @param {string} [props.autoComplete] - Autocomplete value for the input field.
* @param {string} [props.placeholder] - Placeholder text for the input field.
* @param {string} props.value - Value of the input field.
@@ -43,7 +42,6 @@ const Field = forwardRef(
isRequired,
isOptional,
optionalLabel,
hasCopy,
autoComplete,
placeholder,
value,
@@ -56,25 +54,54 @@ const Field = forwardRef(
) => {
const theme = useTheme();
// TODO - are we using this feature anywhere ?
const [copy, setCopy] = useState(false);
const handleCopy = () => {
setCopy(true);
setTimeout(() => setCopy(false), 1000);
};
const [isVisible, setVisible] = useState(false);
return (
<Stack gap={theme.gap.xs} className={`field field-${type}`}>
<Stack
gap={theme.gap.xs}
className={`field field-${type}`}
sx={{
"& fieldset": {
borderColor: theme.palette.border.dark,
borderRadius: theme.shape.borderRadius,
},
"&:not(:has(.Mui-disabled)):not(:has(.input-error)) .MuiOutlinedInput-root:hover:not(:has(input:focus)):not(:has(textarea:focus)) fieldset":
{
borderColor: theme.palette.border.dark,
},
"&:has(.input-error) .MuiOutlinedInput-root fieldset": {
borderColor: theme.palette.error.text,
},
}}
>
{label && (
<Typography component="h3">
<Typography
component="h3"
color={theme.palette.text.secondary}
fontWeight={500}
>
{label}
{isRequired ? <span className="field-required">*</span> : ""}
{isRequired ? (
<Typography
component="span"
ml={theme.spacing(1)}
color={theme.palette.error.text}
>
*
</Typography>
) : (
""
)}
{isOptional ? (
<span className="field-optional">
<Typography
component="span"
fontSize="inherit"
fontWeight={400}
ml={theme.spacing(2)}
sx={{ opacity: 0.6 }}
>
{optionalLabel || "(optional)"}
</span>
</Typography>
) : (
""
)}
@@ -115,60 +142,48 @@ const Field = forwardRef(
pl: theme.gap.medium,
}}
>
<Typography component="h5" sx={{ lineHeight: 1 }}>
<Typography
component="h5"
color={theme.palette.text.secondary}
sx={{ lineHeight: 1 }}
>
{https ? "https" : "http"}://
</Typography>
</Stack>
),
endAdornment:
type === "password" ? (
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={() => setVisible((show) => !show)}
tabIndex={-1}
sx={{
color: theme.palette.section.borderColor,
padding: `calc(${theme.gap.xs} / 2)`,
"&:focus": {
outline: "none",
},
"& .MuiTouchRipple-root": {
pointerEvents: "none",
display: "none",
},
}}
>
{!isVisible ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
) : (
hasCopy && (
<InputAdornment className="copy" position="end">
<Button
level="tertiary"
label={copy ? "Copied" : "Copy"}
img={<ContentCopyIcon />}
onClick={handleCopy}
sx={{
borderLeft: `solid 1px ${theme.palette.section.borderColor}`,
lineHeight: 0,
"& .MuiTouchRipple-root": {
pointerEvents: "none",
display: "none",
},
}}
/>
</InputAdornment>
)
),
endAdornment: type === "password" && (
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={() => setVisible((show) => !show)}
tabIndex={-1}
sx={{
color: theme.palette.section.borderColor,
padding: `calc(${theme.gap.xs} / 2)`,
"&:focus": {
outline: "none",
},
"& .MuiTouchRipple-root": {
pointerEvents: "none",
display: "none",
},
}}
>
{!isVisible ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
),
}}
/>
{error && (
<Typography
component="span"
className="input-error"
color={theme.palette.error.text}
mt={theme.gap.xs}
sx={{
opacity: 0.8,
}}
>
{error}
</Typography>
@@ -188,7 +203,6 @@ Field.propTypes = {
isRequired: PropTypes.bool,
isOptional: PropTypes.bool,
optionalLabel: PropTypes.string,
hasCopy: PropTypes.bool,
autoComplete: PropTypes.string,
placeholder: PropTypes.string,
value: PropTypes.string.isRequired,
@@ -1,9 +1,3 @@
.image-field-wrapper h2.MuiTypography-root,
.image-field-wrapper p.MuiTypography-root,
.image-field-wrapper + p.MuiTypography-root,
.MuiStack-root:has(#modal-update-picture) h1.MuiTypography-root {
color: var(--secondary-color-light);
}
.MuiStack-root:has(#modal-update-picture) h1.MuiTypography-root {
font-weight: 600;
}
@@ -20,10 +14,5 @@
}
.image-field-wrapper + p.MuiTypography-root,
.image-field-wrapper p.MuiTypography-root {
opacity: 0.6;
font-size: var(--env-var-font-size-small-plus);
}
.image-field-wrapper h2.MuiTypography-root span {
color: var(--theme-main);
font-weight: 500;
}
+31 -11
View File
@@ -31,19 +31,19 @@ const ImageField = ({ id, src, loading, onChange }) => {
<>
<Box
className="image-field-wrapper"
mt="20px"
mt={theme.spacing(8)}
sx={{
position: "relative",
height: "fit-content",
border: "dashed",
borderRadius: `${theme.shape.borderRadius}px`,
borderRadius: theme.shape.borderRadius,
borderColor: isDragging
? theme.palette.primary.main
: theme.palette.otherColors.graishWhite,
? theme.palette.common.main
: theme.palette.border.light,
borderWidth: "2px",
transition: "0.2s",
"&:hover": {
borderColor: theme.palette.primary.main,
borderColor: theme.palette.common.main,
backgroundColor: "hsl(215, 87%, 51%, 0.05)",
},
}}
@@ -85,20 +85,40 @@ const ImageField = ({ id, src, loading, onChange }) => {
<IconButton
sx={{
pointerEvents: "none",
borderRadius: `${theme.shape.borderRadius}px`,
border: `solid ${theme.shape.borderThick}px ${theme.palette.otherColors.graishWhite}`,
borderRadius: theme.shape.borderRadius,
border: `solid ${theme.shape.borderThick}px ${theme.palette.border.light}`,
boxShadow: theme.shape.boxShadow,
}}
>
<CloudUploadIcon />
</IconButton>
<Typography component="h2">
<span>Click to upload</span> or drag and drop
<Typography component="h2" color={theme.palette.text.tertiary}>
<Typography
component="span"
fontSize="inherit"
color={theme.palette.common.main}
fontWeight={500}
>
Click to upload
</Typography>{" "}
or drag and drop
</Typography>
<Typography
component="p"
color={theme.palette.text.tertiary}
sx={{ opacity: 0.6 }}
>
(maximum size: 3MB)
</Typography>
<Typography component="p">(maximum size: 3MB)</Typography>
</Stack>
</Box>
<Typography component="p">Supported formats: JPG, PNG</Typography>
<Typography
component="p"
color={theme.palette.text.tertiary}
sx={{ opacity: 0.6 }}
>
Supported formats: JPG, PNG
</Typography>
</>
) : (
<Stack direction="row" justifyContent="center">
@@ -0,0 +1 @@
@@ -1,10 +1,16 @@
import PropTypes from "prop-types";
import { FormControlLabel, Radio as MUIRadio, Typography } from "@mui/material";
import { useTheme } from "@emotion/react";
import RadioChecked from "../../../assets/icons/radio-checked.svg?react";
import "./index.css";
/**
* RadioButton component.
* Radio component.
*
* @component
* @example
* // Usage:
* <RadioButton
* <Radio
* title="Radio Button Title"
* desc="Radio Button Description"
* size="small"
@@ -15,47 +21,62 @@
* @param {string} props.title - The title of the radio button.
* @param {string} [props.desc] - The description of the radio button.
* @param {string} [props.size="small"] - The size of the radio button.
* @returns {JSX.Element} - The rendered RadioButton component.
* @returns {JSX.Element} - The rendered Radio component.
*/
import PropTypes from "prop-types";
import { FormControlLabel, Radio, Typography } from "@mui/material";
import { useTheme } from "@emotion/react";
import "./index.css";
function RadioButton(props) {
const Radio = (props) => {
const theme = useTheme();
return (
<FormControlLabel
className="custom-radio-button"
checked={props.checked}
value={props.value}
control={
<Radio
<MUIRadio
id={props.id}
size={props.size}
sx={{ color: theme.palette.secondary.main }}
checkedIcon={<RadioChecked />}
sx={{
color: "transparent",
width: 16,
height: 16,
boxShadow: "inset 0 0 0 1px rgb(16 22 26 / 40%)",
mt: theme.spacing(0.5),
}}
/>
}
onChange={props.onChange}
label={
<>
<Typography component="p">{props.title}</Typography>
<Typography component="h6" mt="2px">
<Typography component="h6" mt={theme.spacing(1)}>
{props.desc}
</Typography>
</>
}
labelPlacement="end"
sx={{ margin: 0, alignItems: "flex-start" }}
sx={{
alignItems: "flex-start",
p: theme.spacing(2.5),
m: theme.spacing(-2.5),
borderRadius: theme.shape.borderRadius,
"&:hover": {
backgroundColor: theme.palette.unresolved.bg,
},
"& .MuiButtonBase-root": {
p: 0,
mr: theme.spacing(6),
},
}}
/>
);
}
};
RadioButton.propTypes = {
Radio.propTypes = {
title: PropTypes.string.isRequired,
desc: PropTypes.string,
size: PropTypes.string,
};
export default RadioButton;
export default Radio;
+2 -36
View File
@@ -1,46 +1,12 @@
.select-wrapper .select-component > .MuiSelect-select {
padding: 0 10px;
height: 34px !important;
display: flex !important;
height: 34px;
display: flex;
align-items: center;
text-transform: capitalize;
line-height: 1;
}
.select-wrapper .MuiInputBase-root:has(> .MuiSelect-select) {
min-width: 150px;
}
.select-wrapper .MuiInputBase-root:has(> .MuiSelect-select),
.MuiMenu-List .MuiMenuItem-root,
.select-wrapper h3.MuiTypography-root {
font-size: var(--env-var-font-size-medium);
color: var(--secondary-color);
}
.select-wrapper h3.MuiTypography-root {
font-weight: 500;
}
.MuiInputBase-root:has(> .MuiSelect-select) fieldset {
border-color: var(--border-color-dark);
}
.MuiInputBase-root:not(.Mui-focused):has(> .MuiSelect-select):hover fieldset {
border-color: var(--border-color-dark);
}
.select-dropdown.MuiPaper-root {
box-shadow: var(--env-var-shadow-1);
border: solid 1px var(--border-color);
border-radius: var(--env-var-radius-1);
}
.select-dropdown .MuiList-root {
min-width: 100px;
}
.select-dropdown li {
font-size: var(--env-var-font-size-medium);
color: var(--secondary-color);
padding: 5px 8px;
border-radius: var(--env-var-radius-1);
}
.select-dropdown li.Mui-selected,
.select-dropdown li.Mui-selected.Mui-focusVisible,
.select-dropdown li.Mui-selected:hover {
background-color: var(--primary-bg-fill);
}
+44 -11
View File
@@ -55,15 +55,22 @@ const Select = ({
const theme = useTheme();
const itemStyles = {
fontSize: "var(--env-var-font-size-medium)",
color: theme.palette.otherColors.bluishGray,
textTransform: "capitalize",
borderRadius: `${theme.shape.borderRadius}px`,
margin: theme.gap.xs,
color: theme.palette.text.tertiary,
borderRadius: theme.shape.borderRadius,
margin: theme.spacing(2),
};
return (
<Stack gap={theme.gap.xs} className="select-wrapper">
{label && <Typography component="h3">{label}</Typography>}
<Stack gap={theme.spacing(2)} className="select-wrapper">
{label && (
<Typography
component="h3"
color={theme.palette.text.secondary}
fontWeight={500}
>
{label}
</Typography>
)}
<MuiSelect
className="select-component"
value={value}
@@ -72,17 +79,43 @@ const Select = ({
inputProps={{ id: id }}
MenuProps={{
PaperProps: {
className: "select-dropdown",
style: {
marginTop: theme.gap.xs,
sx: {
marginTop: theme.spacing(2),
border: 1,
borderColor: theme.palette.border.light,
borderRadius: theme.shape.borderRadius,
boxShadow: theme.shape.boxShadow,
},
},
MenuListProps: {
style: { padding: 0 },
sx: {
p: 0,
"& li": {
color: theme.palette.text.secondary,
fontSize: 13,
px: theme.spacing(4),
py: theme.spacing(2.5),
borderRadius: theme.shape.borderRadius,
},
"& li.Mui-selected, & li.Mui-selected.Mui-focusVisible, & li.Mui-selected:hover":
{
backgroundColor: theme.palette.background.fill,
},
},
},
}}
IconComponent={KeyboardArrowDownIcon}
sx={{ ...sx }}
sx={{
minWidth: "125px",
"& fieldset": {
borderRadius: theme.shape.borderRadius,
borderColor: theme.palette.border.dark,
},
"&:not(.Mui-focused):hover fieldset": {
borderColor: theme.palette.border.dark,
},
...sx,
}}
>
{placeholder && (
<MenuItem
+23 -5
View File
@@ -30,9 +30,9 @@ const BaseLabel = ({ label, styles, children }) => {
<Box
className="label"
sx={{
borderRadius: `${borderRadius}px`,
borderColor: theme.palette.tertiary.main,
color: theme.palette.tertiary.main,
borderRadius: borderRadius,
borderColor: theme.palette.text.tertiary,
color: theme.palette.text.tertiary,
padding: padding,
...styles,
}}
@@ -90,7 +90,7 @@ const ColoredLabel = ({ label, color }) => {
typeof color !== "string" ||
!/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(color)
) {
color = theme.palette.labelGray.color;
color = theme.palette.border.light;
}
// Calculate lighter shades for border and bg
@@ -127,8 +127,26 @@ ColoredLabel.propTypes = {
const StatusLabel = ({ status, text, customStyles }) => {
const theme = useTheme();
const colors = {
up: {
dotColor: theme.palette.success.main,
bgColor: theme.palette.success.bg,
borderColor: theme.palette.success.light,
},
down: {
dotColor: theme.palette.error.text,
bgColor: theme.palette.error.bg,
borderColor: theme.palette.error.light,
},
"cannot resolve": {
dotColor: theme.palette.unresolved.main,
bgColor: theme.palette.unresolved.bg,
borderColor: theme.palette.unresolved.light,
},
};
// Look up the color for the status
const { borderColor, bgColor, dotColor } = theme.label[status];
const { borderColor, bgColor, dotColor } = colors[status];
return (
<BaseLabel
+7 -7
View File
@@ -16,24 +16,24 @@ const Link = ({ level, label, url }) => {
const levelConfig = {
primary: {},
secondary: {
color: theme.palette.otherColors.bluishGray,
color: theme.palette.text.secondary,
sx: {
":hover": {
color: theme.palette.otherColors.bluishGray,
color: theme.palette.text.secondary,
},
},
},
tertiary: {
color: theme.palette.tertiary.main,
color: theme.palette.text.tertiary,
sx: {
textDecoration: "underline",
textDecorationStyle: "dashed",
textDecorationColor: theme.palette.primary.main,
textDecorationColor: theme.palette.common.main,
textUnderlineOffset: "1px",
":hover": {
color: theme.palette.tertiary.main,
textDecorationColor: theme.palette.primary.main,
backgroundColor: theme.palette.tertiary.linkHover,
color: theme.palette.text.tertiary,
textDecorationColor: theme.palette.common.main,
backgroundColor: theme.palette.background.fill,
},
},
},
@@ -1,32 +1,10 @@
.progress-bar-container {
background-color: #fafafa;
padding: var(--env-var-spacing-1-plus);
}
.progress-bar-container h2.MuiTypography-root,
.progress-bar-container p.MuiTypography-root {
color: var(--secondary-color-light);
font-size: var(--env-var-font-size-medium);
}
.progress-bar-container p.MuiTypography-root {
opacity: 0.6;
}
.progress-bar-container p.MuiTypography-root:has(span) {
font-size: 12px;
}
.progress-bar-container p.MuiTypography-root span {
padding-left: 2px;
}
.progress-bar-container:has(p.input-error){
border-color: var(--error-color);
background-color: var(--error-bg);
padding: 8px var(--env-var-spacing-1-plus);
}
.progress-bar-container p.input-error{
color: var(--error-color);
opacity: 0.8;
}
.progress-bar-container:has(p.input-error)>.MuiStack-root>svg{
fill: var(--error-color);
width: 20px;
height: 20px;
}
+44 -19
View File
@@ -32,21 +32,36 @@ const ProgressUpload = ({
error,
}) => {
const theme = useTheme();
return (
<Box
className="progress-bar-container"
mt="20px"
mt={theme.spacing(10)}
p={theme.spacing(8)}
sx={{
minWidth: "200px",
height: "fit-content",
borderRadius: `${theme.shape.borderRadius}px`,
border: `solid 1px ${theme.palette.otherColors.graishWhite}`,
borderRadius: theme.shape.borderRadius,
border: 1,
borderColor: theme.palette.border.light,
backgroundColor: "#fafafa",
"&:has(.input-error)": {
borderColor: theme.palette.error.main,
backgroundColor: theme.palette.error.bg,
py: theme.spacing(4),
px: theme.spacing(8),
"& > .MuiStack-root > svg": {
fill: theme.palette.error.text,
width: "20px",
height: "20px",
},
},
}}
>
<Stack
direction="row"
mb={error ? "0" : "10px"}
gap="10px"
mb={error ? 0 : theme.spacing(5)}
gap={theme.spacing(5)}
alignItems={error ? "center" : "flex-end"}
>
{error ? (
@@ -54,10 +69,11 @@ const ProgressUpload = ({
) : icon ? (
<IconButton
sx={{
backgroundColor: theme.palette.otherColors.white,
backgroundColor: theme.palette.background.main,
pointerEvents: "none",
borderRadius: `${theme.shape.borderRadius}px`,
border: `solid ${theme.shape.borderThick}px ${theme.palette.otherColors.graishWhite}`,
borderRadius: theme.shape.borderRadius,
border: 2,
borderColor: theme.palette.border.light,
boxShadow: theme.shape.boxShadow,
}}
>
@@ -67,15 +83,21 @@ const ProgressUpload = ({
""
)}
{error ? (
<Typography component="p" className="input-error">
<Typography
component="p"
className="input-error"
color={theme.palette.error.text}
>
{error}
</Typography>
) : (
<Box>
<Typography component="h2" mb="5px">
<Box color={theme.palette.text.tertiary}>
<Typography component="h2" mb={theme.spacing(1.5)}>
{error ? error : label}
</Typography>
<Typography component="p">{!error && size}</Typography>
<Typography component="p" sx={{ opacity: 0.6 }}>
{!error && size}
</Typography>
</Box>
)}
<IconButton
@@ -85,9 +107,9 @@ const ProgressUpload = ({
? {
alignSelf: "flex-start",
ml: "auto",
mr: "-5px",
mt: "-5px",
padding: "5px",
mr: theme.spacing(-2.5),
mt: theme.spacing(-2.5),
padding: theme.spacing(2.5),
"&:focus": {
outline: "none",
},
@@ -109,20 +131,23 @@ const ProgressUpload = ({
</Stack>
{!error ? (
<Stack direction="row" alignItems="center">
<Box sx={{ width: "100%", mr: "10px" }}>
<Box sx={{ width: "100%", mr: theme.spacing(5) }}>
<LinearProgress
variant="determinate"
value={progress}
sx={{
width: "100%",
height: "10px",
borderRadius: `${theme.shape.borderRadius}px`,
borderRadius: theme.shape.borderRadius,
maxWidth: "500px",
backgroundColor: theme.palette.otherColors.graishWhite,
backgroundColor: theme.palette.border.light,
}}
/>
</Box>
<Typography component="p" sx={{ minWidth: "max-content" }}>
<Typography
component="p"
sx={{ minWidth: "max-content", opacity: 0.6 }}
>
{progress}
<span>%</span>
</Typography>
@@ -1,15 +0,0 @@
.create-monitor-form .custom-radio-button.MuiFormControlLabel-root,
.configure-monitor .custom-radio-button.MuiFormControlLabel-root {
padding: 5px;
margin: -5px;
border-radius: var(--env-var-radius-1);
}
.create-monitor-form .custom-radio-button.MuiFormControlLabel-root:hover,
.configure-monitor .custom-radio-button.MuiFormControlLabel-root:hover {
background-color: var(--unresolved-bg);
}
.custom-radio-button.MuiFormControlLabel-root .MuiButtonBase-root {
margin-right: var(--env-var-spacing-1);
padding: 0;
}
-80
View File
@@ -1,16 +1,8 @@
aside .selected-path,
.sidebar-popup .selected-path,
aside .MuiListItemButton-root:hover {
background-color: var(--primary-bg-accent);
}
aside .MuiList-root svg {
width: 20px;
height: 20px;
opacity: 0.9;
}
aside .MuiList-root svg path {
stroke: var(--secondary-color-light);
}
aside span.MuiTypography-root {
font-size: var(--env-var-font-size-medium);
line-height: 1;
@@ -26,11 +18,6 @@ aside .MuiListSubheader-root {
margin-bottom: 2px;
opacity: 0.6;
}
aside span.MuiTypography-root,
aside p.MuiTypography-root,
aside .MuiListSubheader-root {
color: var(--secondary-color);
}
aside p.MuiTypography-root {
font-size: var(--env-var-font-size-small);
opacity: 0.8;
@@ -47,82 +34,15 @@ aside .selected-path span.MuiTypography-root {
aside .MuiCollapse-wrapperInner .MuiList-root > .MuiListItemButton-root {
position: relative;
}
aside .MuiDivider-root {
border-color: var(--border-color);
}
aside
.MuiCollapse-wrapperInner
.MuiList-root
> .MuiListItemButton-root::before {
content: "";
position: absolute;
left: -7px;
top: 0;
height: 100%;
width: 100%;
border-left: solid 1px var(--secondary-color);
opacity: 0.2;
}
aside
.MuiCollapse-wrapperInner
.MuiList-root
> .MuiListItemButton-root:last-child::before {
height: 50%;
}
aside .MuiCollapse-wrapperInner .MuiList-root svg,
aside .MuiList-root .MuiListItemText-root + svg {
width: 18px;
height: 18px;
}
aside .MuiCollapse-wrapperInner .MuiList-root > .MuiListItemButton-root::after {
content: "";
position: absolute;
left: -8px;
top: 45%;
height: 3px;
width: 3px;
border-radius: 50%;
background-color: #d6d9dd;
}
aside
.MuiCollapse-wrapperInner
.MuiList-root
> .selected-path.MuiListItemButton-root::after {
background-color: var(--secondary-color-light);
transform: scale(1.2);
}
.sidebar-popup .MuiPaper-root {
box-shadow: var(--env-var-shadow-1);
border: solid 1px var(--border-color);
border-radius: var(--env-var-radius-1);
gap: 1px;
}
.sidebar-popup .MuiList-root {
padding: 3px;
min-width: 100px;
}
.sidebar-popup li.MuiButtonBase-root {
font-size: var(--env-var-font-size-medium);
color: var(--secondary-color);
padding: 5px 8px;
border-radius: var(--env-var-radius-1);
}
.sidebar-popup li.MuiButtonBase-root:hover {
background-color: var(--primary-bg-accent);
}
.sidebar-popup li.MuiButtonBase-root:has(.MuiBox-root):hover {
background-color: white;
}
.sidebar-popup li.MuiButtonBase-root:has(.MuiBox-root) {
padding-bottom: 0;
}
.sidebar-popup .MuiModal-root p.MuiTypography-root {
font-size: var(--env-var-font-size-medium);
color: var(--secondary-color-light);
}
.sidebar-popup svg {
width: 16px;
height: 16px;
+161 -60
View File
@@ -124,21 +124,33 @@ function Sidebar() {
<Stack
component="aside"
className={collapsed ? "collapsed" : "expanded"}
gap={theme.gap.medium}
gap={theme.spacing(6)}
sx={{
"& .selected-path, & .MuiListItemButton-root:hover": {
backgroundColor: theme.palette.background.accent,
},
"& .MuiList-root svg path": {
stroke: theme.palette.text.tertiary,
},
"& p, & span, & .MuiListSubheader-root": {
color: theme.palette.text.secondary,
},
}}
>
<Stack pt={theme.gap.medium} pb={theme.gap.large} pl={theme.gap.ml}>
<Stack direction="row" alignItems="center" gap={theme.gap.small}>
<Stack pt={theme.spacing(6)} pb={theme.spacing(12)} pl={theme.spacing(8)}>
<Stack direction="row" alignItems="center" gap={theme.spacing(4)}>
<Stack
justifyContent="center"
alignItems="center"
minWidth={theme.gap.lgplus}
minHeight={theme.gap.lgplus}
fontSize="18px"
minWidth={theme.spacing(16)}
minHeight={theme.spacing(16)}
pl="1px"
fontSize={18}
color="white"
sx={{
position: "relative",
backgroundColor: theme.palette.primary.main,
borderRadius: "4px",
backgroundColor: theme.palette.common.main,
borderRadius: theme.shape.borderRadius,
userSelect: "none",
}}
>
@@ -146,7 +158,7 @@ function Sidebar() {
</Stack>
<Typography
component="span"
mt={theme.gap.xs}
mt={theme.spacing(2)}
sx={{ opacity: 0.8, fontWeight: 500 }}
>
BlueWave Uptime
@@ -158,20 +170,21 @@ function Sidebar() {
top: 60,
right: 0,
transform: `translate(50%, 0)`,
backgroundColor: theme.palette.otherColors.fillGray,
border: `solid 1px ${theme.palette.otherColors.graishWhite}`,
p: "5px",
backgroundColor: theme.palette.background.fill,
border: 1,
borderColor: theme.palette.border.light,
p: theme.spacing(2.5),
"& svg": {
width: theme.gap.ml,
height: theme.gap.ml,
width: theme.spacing(8),
height: theme.spacing(8),
"& path": {
stroke: theme.palette.otherColors.bluishGray,
stroke: theme.palette.text.secondary,
},
},
"&:focus": { outline: "none" },
"&:hover": {
backgroundColor: "#e3e3e3",
borderColor: theme.palette.otherColors.graishWhite,
backgroundColor: theme.palette.border.light,
borderColor: theme.palette.border.light,
},
}}
onClick={() => {
@@ -192,15 +205,15 @@ function Sidebar() {
component="div"
id="nested-menu-subheader"
sx={{
pt: theme.gap.small,
px: collapsed ? theme.gap.xs : theme.gap.small,
backgroundColor: "transparent"
pt: theme.spacing(4),
px: collapsed ? theme.spacing(2) : theme.spacing(4),
backgroundColor: "transparent",
}}
>
Menu
</ListSubheader>
}
sx={{ px: theme.gap.medium }}
sx={{ px: theme.spacing(6) }}
>
{menu.map((item) =>
item.path ? (
@@ -229,9 +242,9 @@ function Sidebar() {
onClick={() => navigate(`/${item.path}`)}
sx={{
height: "37px",
gap: theme.gap.small,
borderRadius: `${theme.shape.borderRadius}px`,
px: theme.gap.small,
gap: theme.spacing(4),
borderRadius: theme.shape.borderRadius,
px: theme.spacing(4),
}}
>
<ListItemIcon sx={{ minWidth: 0 }}>{item.icon}</ListItemIcon>
@@ -266,9 +279,9 @@ function Sidebar() {
onClick={(event) => openPopup(event, item.name)}
sx={{
position: "relative",
gap: theme.gap.small,
borderRadius: `${theme.shape.borderRadius}px`,
px: theme.gap.small,
gap: theme.spacing(4),
borderRadius: theme.shape.borderRadius,
px: theme.spacing(4),
}}
>
<ListItemIcon sx={{ minWidth: 0 }}>{item.icon}</ListItemIcon>
@@ -284,7 +297,38 @@ function Sidebar() {
vertical: "top",
horizontal: "right",
}}
sx={{ ml: theme.gap.ml }}
slotProps={{
paper: {
sx: {
border: 1,
borderColor: theme.palette.border.light,
borderRadius: theme.shape.borderRadius,
boxShadow: theme.shape.boxShadow,
},
},
}}
MenuListProps={{
sx: {
p: 3,
minWidth: "100px",
"& li": {
color: theme.palette.text.secondary,
fontSize: 13,
px: theme.spacing(4),
py: theme.spacing(2.5),
borderRadius: theme.shape.borderRadius,
},
"& li:hover": {
backgroundColor: theme.palette.background.accent,
},
},
}}
sx={{
ml: theme.spacing(8),
"& .selected-path": {
backgroundColor: theme.palette.background.accent,
},
}}
>
{item.nested.map((child) => {
if (
@@ -308,9 +352,9 @@ function Sidebar() {
closePopup();
}}
sx={{
gap: theme.gap.small,
borderRadius: `${theme.shape.borderRadius}px`,
pl: theme.gap.small,
gap: theme.spacing(4),
borderRadius: theme.shape.borderRadius,
pl: theme.spacing(4),
mb: "1px",
}}
>
@@ -331,9 +375,9 @@ function Sidebar() {
}))
}
sx={{
gap: theme.gap.small,
borderRadius: `${theme.shape.borderRadius}px`,
px: theme.gap.small,
gap: theme.spacing(4),
borderRadius: theme.shape.borderRadius,
px: theme.spacing(4),
}}
>
<ListItemIcon sx={{ minWidth: 0 }}>{item.icon}</ListItemIcon>
@@ -344,7 +388,7 @@ function Sidebar() {
<List
component="div"
disablePadding
sx={{ pl: theme.gap.large }}
sx={{ pl: theme.spacing(12) }}
>
{item.nested.map((child) => {
if (
@@ -365,9 +409,35 @@ function Sidebar() {
key={child.path}
onClick={() => navigate(`/${child.path}`)}
sx={{
gap: theme.gap.small,
borderRadius: `${theme.shape.borderRadius}px`,
pl: theme.gap.small,
gap: theme.spacing(4),
borderRadius: theme.shape.borderRadius,
pl: theme.spacing(4),
"&::before": {
content: `""`,
position: "absolute",
top: 0,
left: "-7px",
height: "100%",
borderLeft: 1,
borderLeftColor: "#d6d9dd",
},
"&:last-child::before": {
height: "50%",
},
"&::after": {
content: `""`,
position: "absolute",
top: "45%",
left: "-8px",
height: "3px",
width: "3px",
borderRadius: "50%",
backgroundColor: "#d6d9dd",
},
"&.selected-path::after": {
backgroundColor: theme.palette.text.tertiary,
transform: "scale(1.2)",
},
}}
>
<ListItemIcon sx={{ minWidth: 0 }}>
@@ -383,7 +453,9 @@ function Sidebar() {
)
)}
</List>
<Divider sx={{ my: theme.gap.small }} />
<Divider
sx={{ my: theme.spacing(4), borderColor: theme.palette.border.light }}
/>
{/* other */}
<List
component="nav"
@@ -393,15 +465,15 @@ function Sidebar() {
component="div"
id="nested-other-subheader"
sx={{
pt: theme.gap.small,
px: collapsed ? 0 : theme.gap.small,
backgroundColor: "transparent"
pt: theme.spacing(4),
px: collapsed ? 0 : theme.spacing(4),
backgroundColor: "transparent",
}}
>
Other
</ListSubheader>
}
sx={{ px: theme.gap.medium }}
sx={{ px: theme.spacing(6) }}
>
{other.map((item) => (
<Tooltip
@@ -436,9 +508,9 @@ function Sidebar() {
: navigate(`/${item.path}`)
}
sx={{
gap: theme.gap.small,
borderRadius: `${theme.shape.borderRadius}px`,
px: theme.gap.small,
gap: theme.spacing(4),
borderRadius: theme.shape.borderRadius,
px: theme.spacing(4),
}}
>
<ListItemIcon sx={{ minWidth: 0 }}>{item.icon}</ListItemIcon>
@@ -447,16 +519,16 @@ function Sidebar() {
</Tooltip>
))}
</List>
<Divider sx={{ mt: "auto" }} />
<Divider sx={{ mt: "auto", borderColor: theme.palette.border.light }} />
<Stack
direction="row"
height="50px"
alignItems="center"
py={theme.gap.small}
px={theme.gap.ml}
gap={theme.gap.xs}
borderRadius={`${theme.shape.borderRadius}px`}
py={theme.spacing(4)}
px={theme.spacing(8)}
gap={theme.spacing(2)}
borderRadius={theme.shape.borderRadius}
>
{collapsed ? (
<>
@@ -492,27 +564,56 @@ function Sidebar() {
vertical: "top",
horizontal: "right",
}}
sx={{ ml: theme.gap.ml }}
slotProps={{
paper: {
sx: {
border: 1,
borderColor: theme.palette.border.light,
borderRadius: theme.shape.borderRadius,
boxShadow: theme.shape.boxShadow,
},
},
}}
MenuListProps={{
sx: {
p: 3,
minWidth: "100px",
"& li": {
color: theme.palette.text.secondary,
fontSize: 13,
px: theme.spacing(4),
py: theme.spacing(2.5),
borderRadius: theme.shape.borderRadius,
},
"& li:hover": {
backgroundColor: theme.palette.background.accent,
},
"& li:has(.MuiBox-root):hover": {
backgroundColor: theme.palette.background.main,
},
},
}}
sx={{ ml: theme.spacing(8) }}
>
<MenuItem sx={{ cursor: "default", minWidth: "150px" }}>
<Box>
<Typography component="span" fontWeight={500} fontSize="13px">
<Typography component="span" fontWeight={500} fontSize={13}>
{authState.user?.firstName} {authState.user?.lastName}
</Typography>
<Typography
sx={{ textTransform: "capitalize", fontSize: "12px" }}
sx={{ textTransform: "capitalize", fontSize: 12 }}
>
{authState.user?.role}
</Typography>
</Box>
</MenuItem>
<Divider />
<Divider sx={{ borderColor: theme.palette.border.light }} />
<MenuItem
onClick={logout}
sx={{
gap: theme.gap.small,
borderRadius: `${theme.shape.borderRadius}px`,
pl: theme.gap.small,
gap: theme.spacing(4),
borderRadius: theme.shape.borderRadius,
pl: theme.spacing(4),
}}
>
<LogoutSvg />
@@ -523,7 +624,7 @@ function Sidebar() {
) : (
<>
<Avatar small={true} />
<Box ml={theme.gap.xs}>
<Box ml={theme.spacing(2)}>
<Typography component="span" fontWeight={500}>
{authState.user?.firstName} {authState.user?.lastName}
</Typography>
@@ -531,7 +632,7 @@ function Sidebar() {
{authState.user?.role}
</Typography>
</Box>
<Tooltip title="Log Out">
<Tooltip title="Log Out" disableInteractive>
<IconButton
sx={{ ml: "auto", "&:focus": { outline: "none" } }}
onClick={logout}
@@ -1,6 +1,6 @@
import "./index.css";
import { useState } from "react";
import RadioButton from "../../../Components/RadioButton";
import Radio from "../../../Components/Inputs/Radio";
import Button from "../../../Components/Button";
import { Box, ButtonGroup, Stack, Typography } from "@mui/material";
import { useSelector, useDispatch } from "react-redux";
@@ -211,7 +211,7 @@ const CreateMonitor = () => {
</Box>
<Stack gap={theme.gap.large}>
<Stack gap={theme.gap.medium}>
<RadioButton
<Radio
id="monitor-checks-http"
title="Website monitoring"
desc="Use HTTP(s) to monitor your website or API endpoint."
@@ -245,7 +245,7 @@ const CreateMonitor = () => {
""
)}
</Stack>
<RadioButton
<Radio
id="monitor-checks-ping"
title="Ping monitoring"
desc="Check whether your server is available or not."
@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 8C0 3.58172 3.58172 0 8 0C12.4183 0 16 3.58172 16 8C16 12.4183 12.4183 16 8 16C3.58172 16 0 12.4183 0 8Z" fill="#1570EF"/>
<path d="M5 8C5 6.34315 6.34315 5 8 5C9.65685 5 11 6.34315 11 8C11 9.65685 9.65685 11 8 11C6.34315 11 5 9.65685 5 8Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 371 B