diff --git a/client/src/Components/ArrowLeft/index.jsx b/client/src/Components/ArrowLeft/index.jsx new file mode 100644 index 000000000..7909441f3 --- /dev/null +++ b/client/src/Components/ArrowLeft/index.jsx @@ -0,0 +1,35 @@ +import LeftArrow from "../../assets/icons/left-arrow.svg?react"; +import LeftArrowDouble from "../../assets/icons/left-arrow-double.svg?react"; +import LeftArrowLong from "../../assets/icons/left-arrow-long.svg?react"; +import PropTypes from "prop-types"; + +const ArrowLeft = ({ type, color = "#667085", ...props }) => { + if (type === "double") { + return ( + + ); + } else if (type === "long") { + return ( + + ); + } else { + return ( + + ); + } +}; + +ArrowLeft.propTypes = { + color: PropTypes.string, + type: PropTypes.oneOf(["double", "long", "default"]), +}; +export default ArrowLeft; diff --git a/client/src/Components/ArrowRight/index.jsx b/client/src/Components/ArrowRight/index.jsx new file mode 100644 index 000000000..335bc19f2 --- /dev/null +++ b/client/src/Components/ArrowRight/index.jsx @@ -0,0 +1,28 @@ +import RightArrow from "../../assets/icons/right-arrow.svg?react"; +import RightArrowDouble from "../../assets/icons/right-arrow-double.svg?react"; +import PropTypes from "prop-types"; + +const ArrowRight = ({ type, color = "#667085", ...props }) => { + if (type === "double") { + return ( + + ); + } else { + return ( + + ); + } +}; + +ArrowRight.propTypes = { + type: PropTypes.oneOf(["double", "default"]), + color: PropTypes.string, +}; + +export default ArrowRight; diff --git a/client/src/Components/Avatar/index.jsx b/client/src/Components/Avatar/index.jsx index aa2050827..d089080ff 100644 --- a/client/src/Components/Avatar/index.jsx +++ b/client/src/Components/Avatar/index.jsx @@ -15,7 +15,7 @@ import { useTheme } from "@emotion/react"; * */ -const Avatar = ({ src, small, sx }) => { +const Avatar = ({ src, small, sx, onClick = () => {} }) => { const { user } = useSelector((state) => state.auth); const theme = useTheme(); @@ -31,6 +31,7 @@ const Avatar = ({ src, small, sx }) => { return ( div { min-height: calc(100vh - var(--env-var-spacing-2) * 2); diff --git a/client/src/Components/Sidebar/components/authFooter.jsx b/client/src/Components/Sidebar/components/authFooter.jsx new file mode 100644 index 000000000..0e6937913 --- /dev/null +++ b/client/src/Components/Sidebar/components/authFooter.jsx @@ -0,0 +1,286 @@ +import Stack from "@mui/material/Stack"; +import Box from "@mui/material/Box"; +import Typography from "@mui/material/Typography"; +import Tooltip from "@mui/material/Tooltip"; +import IconButton from "@mui/material/IconButton"; +import Avatar from "../../Avatar"; +import ThemeSwitch from "../../ThemeSwitch"; +import Menu from "@mui/material/Menu"; +import MenuItem from "@mui/material/MenuItem"; +import Divider from "@mui/material/Divider"; +import DotsVertical from "../../../assets/icons/dots-vertical.svg?react"; +import LogoutSvg from "../../../assets/icons/logout.svg?react"; + +import { useTheme } from "@emotion/react"; +import { useSelector } from "react-redux"; +import { useTranslation } from "react-i18next"; +import { useState } from "react"; +import { useNavigate } from "react-router"; +import { clearAuthState } from "../../../Features/Auth/authSlice"; +import { useDispatch } from "react-redux"; +import PropTypes from "prop-types"; + +const getFilteredAccountMenuItems = (user, items) => { + if (!user) return []; + + let filtered = [...items]; + + if (user.role?.includes("demo")) { + filtered = filtered.filter((item) => item.name !== "Password"); + } + + if (!user.role?.includes("superadmin")) { + filtered = filtered.filter((item) => item.name !== "Team"); + } + + return filtered; +}; + +const getRoleDisplayText = (user, t) => { + if (!user?.role) return ""; + + if (user.role.includes("superadmin")) return t("roles.superAdmin"); + if (user.role.includes("admin")) return t("roles.admin"); + if (user.role.includes("user")) return t("roles.teamMember"); + if (user.role.includes("demo")) return t("roles.demoUser"); + + return user.role; +}; + +const AuthFooter = ({ collapsed, accountMenuItems }) => { + const { t } = useTranslation(); + const theme = useTheme(); + const authState = useSelector((state) => state.auth); + const navigate = useNavigate(); + const dispatch = useDispatch(); + + const [anchorEl, setAnchorEl] = useState(null); + + const openPopup = (event) => { + setAnchorEl(event.currentTarget); + }; + + const closePopup = () => { + setAnchorEl(null); + }; + + const logout = async () => { + dispatch(clearAuthState()); + navigate("/login"); + }; + const renderAccountMenuItems = (user, items) => { + const filteredItems = getFilteredAccountMenuItems(user, items); + + return filteredItems.map((item) => ( + { + closePopup(); + navigate(item.path); + }} + sx={{ + gap: theme.spacing(2), + borderRadius: theme.shape.borderRadius, + pl: theme.spacing(4), + }} + > + {item.icon} + {item.name} + + )); + }; + return ( + + collapsed && openPopup(e)} + sx={{ + cursor: collapsed ? "pointer" : "default", + }} + /> + + + + + {authState.user?.firstName} {authState.user?.lastName} + + + {getRoleDisplayText(authState.user, t)} + + + + + + openPopup(event)} + > + + + + + + + {collapsed && ( + + + + {authState.user?.firstName} {authState.user?.lastName} + + + {authState.user?.role} + + + + )} + {/* TODO Do we need two dividers? */} + {collapsed && } + {/* */} + {renderAccountMenuItems(authState.user, accountMenuItems)} + + + {t("menu.logOut", "Log out")} + + + + ); +}; + +AuthFooter.propTypes = { + collapsed: PropTypes.bool, + accountMenuItems: PropTypes.array, +}; + +export default AuthFooter; diff --git a/client/src/Components/Sidebar/components/collapseButton.jsx b/client/src/Components/Sidebar/components/collapseButton.jsx new file mode 100644 index 000000000..e7c382e5a --- /dev/null +++ b/client/src/Components/Sidebar/components/collapseButton.jsx @@ -0,0 +1,55 @@ +import IconButton from "@mui/material/IconButton"; +import ArrowRight from "../../ArrowRight"; +import ArrowLeft from "../../ArrowLeft"; +import { useTheme } from "@mui/material/styles"; +import { useDispatch } from "react-redux"; +import { toggleSidebar } from "../../../Features/UI/uiSlice"; +import PropTypes from "prop-types"; + +const CollapseButton = ({ collapsed }) => { + const theme = useTheme(); + const dispatch = useDispatch(); + const arrowIcon = collapsed ? ( + + ) : ( + + ); + return ( + { + dispatch(toggleSidebar()); + }} + > + {arrowIcon} + + ); +}; + +CollapseButton.propTypes = { + collapsed: PropTypes.bool.isRequired, +}; +export default CollapseButton; diff --git a/client/src/Components/Sidebar/components/logo.jsx b/client/src/Components/Sidebar/components/logo.jsx new file mode 100644 index 000000000..7a59f406d --- /dev/null +++ b/client/src/Components/Sidebar/components/logo.jsx @@ -0,0 +1,67 @@ +import Stack from "@mui/material/Stack"; +import Box from "@mui/material/Box"; +import Typography from "@mui/material/Typography"; +import { useTheme } from "@mui/material/styles"; +import { useNavigate } from "react-router"; +import { useTranslation } from "react-i18next"; +import PropTypes from "prop-types"; + +const Logo = ({ collapsed }) => { + const { t } = useTranslation(); + const theme = useTheme(); + const navigate = useNavigate(); + + return ( + navigate("/")} + sx={{ cursor: "pointer" }} + > + + C + + + {" "} + + {t("common.appName")} + + + + ); +}; + +Logo.propTypes = { + collapsed: PropTypes.bool, +}; + +export default Logo; diff --git a/client/src/Components/Sidebar/components/navItem.jsx b/client/src/Components/Sidebar/components/navItem.jsx new file mode 100644 index 000000000..2c569edde --- /dev/null +++ b/client/src/Components/Sidebar/components/navItem.jsx @@ -0,0 +1,97 @@ +import Tooltip from "@mui/material/Tooltip"; +import ListItemButton from "@mui/material/ListItemButton"; +import ListItemIcon from "@mui/material/ListItemIcon"; +import Box from "@mui/material/Box"; +import Typography from "@mui/material/Typography"; +import { useTheme } from "@emotion/react"; +import PropTypes from "prop-types"; + +const NavItem = ({ item, collapsed, selected, onClick }) => { + const theme = useTheme(); + const iconStroke = selected + ? theme.palette.primary.contrastText + : theme.palette.primary.contrastTextTertiary; + + const buttonBgColor = selected ? theme.palette.secondary.main : "transparent"; + const buttonBgHoverColor = selected + ? theme.palette.secondary.main + : theme.palette.tertiary.main; + const fontWeight = selected ? 600 : 400; + return ( + + + + {item.icon} + + + + {item.name} + + + + + ); +}; + +NavItem.propTypes = { + item: PropTypes.object, + collapsed: PropTypes.bool, + selected: PropTypes.bool, + onClick: PropTypes.func, +}; +export default NavItem; diff --git a/client/src/Components/Sidebar/index.css b/client/src/Components/Sidebar/index.css deleted file mode 100644 index ef921acca..000000000 --- a/client/src/Components/Sidebar/index.css +++ /dev/null @@ -1,106 +0,0 @@ -/* TODO */ -aside .MuiList-root svg { - width: 20px; - height: 20px; - opacity: 0.9; -} -aside span.MuiTypography-root { - font-size: var(--env-var-font-size-medium); - line-height: 1; -} -aside .MuiStack-root + span.MuiTypography-root { - font-size: var(--env-var-font-size-medium-plus); -} -aside .MuiListSubheader-root { - font-size: var(--env-var-font-size-small); - font-weight: 500; - line-height: 1.5; - text-transform: uppercase; - margin-bottom: 2px; - opacity: 0.6; -} -aside p.MuiTypography-root { - font-size: var(--env-var-font-size-small); - opacity: 0.8; -} -aside .MuiListItemButton-root:not(.selected-path) > * { - opacity: 0.9; -} -aside .selected-path > * { - opacity: 1; -} -aside .selected-path span.MuiTypography-root { - font-weight: 600; -} -aside .MuiCollapse-wrapperInner .MuiList-root > .MuiListItemButton-root { - position: relative; -} -aside .MuiCollapse-wrapperInner .MuiList-root svg, -aside .MuiList-root .MuiListItemText-root + svg { - width: 18px; - height: 18px; -} - -.sidebar-popup li.MuiButtonBase-root:has(.MuiBox-root) { - padding-bottom: 0; -} -.sidebar-popup svg { - width: 16px; - height: 16px; - opacity: 0.9; -} - -/* TRANSITIONS */ -aside { - flex: 1; - transition: max-width 650ms cubic-bezier(0.36, -0.01, 0, 0.77); -} -.home-layout aside.collapsed { - max-width: 64px; -} - -aside.expanded .MuiTypography-root, -aside.expanded p.MuiTypography-root, -aside.expanded .MuiListItemText-root + svg, -aside.expanded .MuiAvatar-root + .MuiBox-root + .MuiIconButton-root { - visibility: visible; - animation: fadeIn 1s ease; -} - -aside.collapsed .MuiTypography-root, -aside.collapsed p.MuiTypography-root, -aside.collapsed .MuiListItemText-root + svg, -aside.collapsed .MuiAvatar-root + .MuiBox-root + .MuiIconButton-root { - opacity: 0; - visibility: hidden; -} - -aside .MuiListSubheader-root { - transition: padding 200ms ease; -} - -.sidebar-delay-fade { - opacity: 0; - visibility: hidden; - transition: opacity 0.3s ease; -} - -aside.expanded.sidebar-ready .sidebar-delay-fade { - opacity: 1; - visibility: visible; -} - -@keyframes fadeIn { - 0% { - opacity: 0; - visibility: hidden; - } - 30% { - opacity: 0; - visibility: hidden; - } - 100% { - opacity: 0.9; - visibility: visible; - } -} diff --git a/client/src/Components/Sidebar/index.jsx b/client/src/Components/Sidebar/index.jsx index 219ceff1e..6b7b6577c 100644 --- a/client/src/Components/Sidebar/index.jsx +++ b/client/src/Components/Sidebar/index.jsx @@ -1,26 +1,16 @@ -import React, { useEffect, useState, useRef } from "react"; -import { - Box, - Collapse, - Divider, - IconButton, - List, - ListItemButton, - ListItemIcon, - ListItemText, - Menu, - MenuItem, - Stack, - Tooltip, - Typography, -} from "@mui/material"; -import ThemeSwitch from "../ThemeSwitch"; -import Avatar from "../Avatar"; +import Stack from "@mui/material/Stack"; + +import List from "@mui/material/List"; +import Logo from "./components/logo"; +import CollapseButton from "./components/collapseButton"; +import Divider from "@mui/material/Divider"; +import NavItem from "./components/navItem"; +import AuthFooter from "./components/authFooter"; + import StarPrompt from "../StarPrompt"; import LockSvg from "../../assets/icons/lock.svg?react"; import UserSvg from "../../assets/icons/user.svg?react"; import TeamSvg from "../../assets/icons/user-two.svg?react"; -import LogoutSvg from "../../assets/icons/logout.svg?react"; import Support from "../../assets/icons/support.svg?react"; import Maintenance from "../../assets/icons/maintenance.svg?react"; import Monitors from "../../assets/icons/monitors.svg?react"; @@ -28,11 +18,6 @@ import Incidents from "../../assets/icons/incidents.svg?react"; import Integrations from "../../assets/icons/integrations.svg?react"; import PageSpeed from "../../assets/icons/page-speed.svg?react"; import Settings from "../../assets/icons/settings.svg?react"; -import ArrowDown from "../../assets/icons/down-arrow.svg?react"; -import ArrowUp from "../../assets/icons/up-arrow.svg?react"; -import ArrowRight from "../../assets/icons/right-arrow.svg?react"; -import ArrowLeft from "../../assets/icons/left-arrow.svg?react"; -import DotsVertical from "../../assets/icons/dots-vertical.svg?react"; import ChangeLog from "../../assets/icons/changeLog.svg?react"; import Docs from "../../assets/icons/docs.svg?react"; import StatusPages from "../../assets/icons/status-pages.svg?react"; @@ -40,17 +25,18 @@ import Discussions from "../../assets/icons/discussions.svg?react"; import Notifications from "../../assets/icons/notifications.svg?react"; import Logs from "../../assets/icons/logs.svg?react"; -import "./index.css"; - // Utils -import { useLocation, useNavigate } from "react-router"; -import { useTheme } from "@emotion/react"; -import { useDispatch, useSelector } from "react-redux"; +import { useTheme } from "@mui/material/styles"; +import { useSelector } from "react-redux"; import { useTranslation } from "react-i18next"; -import { clearAuthState } from "../../Features/Auth/authSlice"; -import { toggleSidebar } from "../../Features/UI/uiSlice"; -import { TurnedIn } from "@mui/icons-material"; -import { rules } from "eslint-plugin-react-refresh"; +import { useNavigate } from "react-router"; + +const URL_MAP = { + support: "https://discord.com/invite/NAb6H3UTjK", + discussions: "https://github.com/bluewave-labs/checkmate/discussions", + docs: "https://bluewavelabs.gitbook.io/checkmate", + changelog: "https://github.com/bluewave-labs/checkmate/releases", +}; const getMenu = (t) => [ { name: t("menu.uptime"), path: "uptime", icon: }, @@ -92,782 +78,94 @@ const getAccountMenuItems = (t) => [ { name: t("menu.team"), path: "account/team", icon: }, ]; -/* TODO this could be a key in nested Path would be the link */ -const URL_MAP = { - support: "https://discord.com/invite/NAb6H3UTjK", - discussions: "https://github.com/bluewave-labs/checkmate/discussions", - docs: "https://bluewavelabs.gitbook.io/checkmate", - changelog: "https://github.com/bluewave-labs/checkmate/releases", -}; - -const PATH_MAP = { - monitors: "Dashboard", - pagespeed: "Dashboard", - infrastructure: "Dashboard", - account: "Account", - settings: "Settings", -}; - -/** - * @component - * Sidebar component serves as a sidebar containing a menu. - * - * @returns {JSX.Element} The JSX element representing the Sidebar component. - */ - -function Sidebar() { +const Sidebar = () => { const theme = useTheme(); - const navigate = useNavigate(); - const location = useLocation(); - const dispatch = useDispatch(); const { t } = useTranslation(); - const authState = useSelector((state) => state.auth); + const navigate = useNavigate(); + // Redux state + const collapsed = useSelector((state) => state.ui.sidebar.collapsed); + const menu = getMenu(t); const otherMenuItems = getOtherMenuItems(t); const accountMenuItems = getAccountMenuItems(t); - const collapsed = useSelector((state) => state.ui.sidebar.collapsed); - const [open, setOpen] = useState({ Dashboard: false, Account: false, Other: false }); - const [anchorEl, setAnchorEl] = useState(null); - const [popup, setPopup] = useState(); - const { user } = useSelector((state) => state.auth); - const sidebarRef = useRef(null); - const [sidebarReady, setSidebarReady] = useState(false); - const TRANSITION_DURATION = 200; - let menu = getMenu(t); - menu = menu.filter((item) => { - if (item.path === "logs") { - return user.role?.includes("admin") || user.role?.includes("superadmin"); - } - return true; - }); - - useEffect(() => { - if (!collapsed) { - setSidebarReady(false); - const timeout = setTimeout(() => { - setSidebarReady(true); - }, TRANSITION_DURATION); - return () => clearTimeout(timeout); - } else { - setSidebarReady(false); - } - }, [collapsed]); - - const renderAccountMenuItems = () => { - let filteredAccountMenuItems = [...accountMenuItems]; - - // If the user is in demo mode, remove the "Password" option - if (user.role?.includes("demo")) { - filteredAccountMenuItems = filteredAccountMenuItems.filter( - (item) => item.name !== "Password" - ); - } - - // If the user is NOT a superadmin, remove the "Team" option - if (user.role && !user.role.includes("superadmin")) { - filteredAccountMenuItems = filteredAccountMenuItems.filter( - (item) => item.name !== "Team" - ); - } - - return filteredAccountMenuItems.map((item) => ( - { - closePopup(); - navigate(item.path); - }} - sx={{ - gap: theme.spacing(2), - borderRadius: theme.shape.borderRadius, - pl: theme.spacing(4), - }} - > - {item.icon} - {item.name} - - )); - }; - - const openPopup = (event, id) => { - setAnchorEl(event.currentTarget); - setPopup(id); - }; - const closePopup = () => { - setAnchorEl(null); - }; - - /** - * Handles logging out the user - * - */ - const logout = async () => { - // Clear auth state - dispatch(clearAuthState()); - navigate("/login"); - }; - - useEffect(() => { - const matchedKey = Object.keys(PATH_MAP).find((key) => - location.pathname.includes(key) - ); - - if (matchedKey) { - setOpen((prev) => ({ ...prev, [PATH_MAP[matchedKey]]: true })); - } - }, [location]); - - const iconColor = theme.palette.primary.contrastTextTertiary; - const sidebarClassName = `${collapsed ? "collapsed" : "expanded"} ${sidebarReady ? "sidebar-ready" : ""}`; - - /* TODO refactor this, there are a some ternaries and comments in the return */ return ( - + + { - setOpen((prev) => - Object.fromEntries(Object.keys(prev).map((key) => [key, false])) + > + {menu.map((item) => { + const selected = location.pathname.startsWith(`/${item.path}`); + return ( + navigate(`/${item.path}`)} + /> ); - dispatch(toggleSidebar()); - }} - > - {collapsed ? : } - - {/* TODO Alignment done using padding. Use single source of truth to that*/} - - {/* TODO Abstract logo into component */} - {/* TODO Turn logo into a link */} - navigate("/")} - sx={{ cursor: "pointer" }} - > - - C - - - {t("common.appName")} - - - - - - {menu.map((item) => { - return item.path ? ( - /* If item has a path */ - - navigate(`/${item.path}`)} - sx={{ - height: "37px", - gap: theme.spacing(4), - borderRadius: theme.shape.borderRadius, - px: theme.spacing(4), - pl: theme.spacing(5), - }} - > - {item.icon} - {item.name} - - - ) : collapsed ? ( - /* TODO Do we ever get here? If item does not have a path and collapsed state is true */ - - - openPopup(event, item.name)} - sx={{ - position: "relative", - gap: theme.spacing(4), - borderRadius: theme.shape.borderRadius, - px: theme.spacing(4), - }} - > - {item.icon} - {item.name} - - - - {item.nested.map((child) => { - if ( - child.name === "Team" && - authState.user?.role && - !authState.user.role.includes("superadmin") - ) { - return null; - } - - return ( - { - const url = URL_MAP[child.path]; - if (url) { - window.open(url, "_blank", "noreferrer"); - } else { - navigate(`/${child.path}`); - } - closePopup(); - }} - sx={{ - gap: theme.spacing(4), - opacity: 0.9, - /* TODO this has no effect? */ - "& svg": { - "& path": { - stroke: theme.palette.primary.contrastTextTertiary, - strokeWidth: 1.1, - }, - }, - }} - > - {child.icon} - {child.name} - - ); - })} - - - ) : ( - /* TODO Do we ever get here? If item does not have a path and collapsed state is false */ - - - setOpen((prev) => ({ - ...Object.fromEntries(Object.keys(prev).map((key) => [key, false])), - [item.name]: !prev[item.name], - })) - } - sx={{ - gap: theme.spacing(4), - borderRadius: theme.shape.borderRadius, - px: theme.spacing(4), - }} - > - {item.icon} - {item.name} - {open[`${item.name}`] ? : } - - - - {item.nested.map((child) => { - if ( - child.name === "Team" && - authState.user?.role && - !authState.user.role.includes("superadmin") - ) { - return null; - } - - return ( - { - const url = URL_MAP[child.path]; - if (url) { - window.open(url, "_blank", "noreferrer"); - } else { - navigate(`/${child.path}`); - } - }} - sx={{ - 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: theme.palette.primary.lowContrast, - }, - "&:last-child::before": { - height: "50%", - }, - "&::after": { - content: `""`, - position: "absolute", - top: "45%", - left: "-8px", - height: "3px", - width: "3px", - borderRadius: "50%", - backgroundColor: theme.palette.primary.lowContrast, - }, - "&.selected-path::after": { - /* TODO what is this selector doing? */ - backgroundColor: theme.palette.primary.contrastTextTertiary, - transform: "scale(1.2)", - }, - }} - > - {child.icon} - {child.name} - - ); - })} - - - - ); - })} - - - + })} + {!collapsed && } - {otherMenuItems.map((item) => { - return item.path ? ( - - { + const url = URL_MAP[item.path]; + if (url) { + window.open(url, "_blank", "noreferrer"); + } else { + navigate(`/${item.path}`); } - onClick={() => { - const url = URL_MAP[item.path]; - if (url) { - window.open(url, "_blank", "noreferrer"); - } else { - navigate(`/${item.path}`); - } - }} - sx={{ - height: "37px", - gap: theme.spacing(4), - borderRadius: theme.shape.borderRadius, - px: theme.spacing(4), - pl: theme.spacing(5), - }} - > - {item.icon} - {item.name} {" "} - - - ) : null; + }} + /> + ); })} - - {collapsed ? ( - <> - - openPopup(event, "logout")} - sx={{ p: 0, "&:focus": { outline: "none" } }} - > - - - - - ) : ( - <> - - - - {authState.user?.firstName} {authState.user?.lastName} - - - {authState.user?.role?.includes("superadmin") - ? t("roles.superAdmin") - : authState.user?.role?.includes("admin") - ? t("roles.admin") - : authState.user?.role?.includes("user") - ? t("roles.teamMember") - : authState.user?.role?.includes("demo") - ? t("roles.demoUser") - : authState.user?.role} - - - - - - openPopup(event, "logout")} - > - - - - - - )} - - {collapsed && ( - - - - {authState.user?.firstName} {authState.user?.lastName} - - - {authState.user?.role} - - - - )} - {/* TODO Do we need two dividers? */} - {collapsed && } - {/* */} - {renderAccountMenuItems()} - - - {t("menu.logOut", "Log out")} - - - + ); -} +}; export default Sidebar; diff --git a/client/src/Components/Table/TablePagination/Actions/index.jsx b/client/src/Components/Table/TablePagination/Actions/index.jsx index 1b654fe9b..dec72446b 100644 --- a/client/src/Components/Table/TablePagination/Actions/index.jsx +++ b/client/src/Components/Table/TablePagination/Actions/index.jsx @@ -1,9 +1,7 @@ import PropTypes from "prop-types"; import { Box, Button } from "@mui/material"; -import LeftArrowDouble from "../../../../assets/icons/left-arrow-double.svg?react"; -import RightArrowDouble from "../../../../assets/icons/right-arrow-double.svg?react"; -import LeftArrow from "../../../../assets/icons/left-arrow.svg?react"; -import RightArrow from "../../../../assets/icons/right-arrow.svg?react"; +import LeftArrow from "../../../ArrowLeft"; +import RightArrow from "../../../ArrowRight"; import { useTheme } from "@emotion/react"; TablePaginationActions.propTypes = { @@ -50,7 +48,7 @@ function TablePaginationActions({ count, page, rowsPerPage, onPageChange }) { disabled={page === 0} aria-label="first page" > - + ); diff --git a/client/src/Utils/Theme/globalTheme.js b/client/src/Utils/Theme/globalTheme.js index 1a8d5e105..6f2a18e71 100644 --- a/client/src/Utils/Theme/globalTheme.js +++ b/client/src/Utils/Theme/globalTheme.js @@ -232,16 +232,16 @@ const baseTheme = (palette) => ({ }, MuiList: { styleOverrides: { - root: { + root: ({ theme }) => ({ padding: 0, - }, + }), }, }, MuiListItemButton: { styleOverrides: { - root: { - transition: "none", - }, + root: ({ theme }) => ({ + transition: "background-color .3s", + }), }, }, MuiListItemText: { @@ -278,6 +278,7 @@ const baseTheme = (palette) => ({ }), }, }, + MuiTableHead: { styleOverrides: { root: ({ theme }) => ({ diff --git a/client/src/assets/icons/left-arrow-double.svg b/client/src/assets/icons/left-arrow-double.svg index 6001a3ead..4cb2a5186 100644 --- a/client/src/assets/icons/left-arrow-double.svg +++ b/client/src/assets/icons/left-arrow-double.svg @@ -1,3 +1,4 @@ - - + + \ No newline at end of file diff --git a/client/src/assets/icons/left-arrow-long.svg b/client/src/assets/icons/left-arrow-long.svg index db9b827ed..56a774730 100644 --- a/client/src/assets/icons/left-arrow-long.svg +++ b/client/src/assets/icons/left-arrow-long.svg @@ -1,3 +1,4 @@ - - + + \ No newline at end of file diff --git a/client/src/assets/icons/left-arrow.svg b/client/src/assets/icons/left-arrow.svg index 8b38c408a..649d1681c 100644 --- a/client/src/assets/icons/left-arrow.svg +++ b/client/src/assets/icons/left-arrow.svg @@ -1,3 +1,4 @@ - - + + \ No newline at end of file diff --git a/client/src/assets/icons/right-arrow-double.svg b/client/src/assets/icons/right-arrow-double.svg index 4235134d7..6ad4882ad 100644 --- a/client/src/assets/icons/right-arrow-double.svg +++ b/client/src/assets/icons/right-arrow-double.svg @@ -1,3 +1,4 @@ - - + + \ No newline at end of file diff --git a/client/src/assets/icons/right-arrow.svg b/client/src/assets/icons/right-arrow.svg index 6b02062f2..77d022798 100644 --- a/client/src/assets/icons/right-arrow.svg +++ b/client/src/assets/icons/right-arrow.svg @@ -1,3 +1,4 @@ - - + + \ No newline at end of file diff --git a/client/src/index.css b/client/src/index.css index f83cdc461..a5d305d46 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -28,6 +28,8 @@ html { --env-var-nav-bar-height: 70px; --env-var-side-bar-width: 250px; + --env-var-side-bar-collapsed-width: 64px; + --env-var-side-bar-auth-footer-height: 50px; --env-var-spacing-1: 12px; --env-var-spacing-1-plus: 16px;