diff --git a/client/src/Components/v1/Layouts/HomeLayout/index.jsx b/client/src/Components/v1/Layouts/HomeLayout/index.jsx
index b078fe048..adadf638f 100644
--- a/client/src/Components/v1/Layouts/HomeLayout/index.jsx
+++ b/client/src/Components/v1/Layouts/HomeLayout/index.jsx
@@ -14,7 +14,6 @@ const HomeLayout = () => {
flexDirection="row"
>
- {/* Spacer for fixed sidebar */}
{
const v2theme = mode === "dark" ? darkTheme : lightTheme;
return (
-
-
+
+
- {children}
-
-
+
+ {children}
+
);
};
diff --git a/client/src/Components/v2/layout/RootLayout.tsx b/client/src/Components/v2/layout/RootLayout.tsx
index e69de29bb..b0c0effe1 100644
--- a/client/src/Components/v2/layout/RootLayout.tsx
+++ b/client/src/Components/v2/layout/RootLayout.tsx
@@ -0,0 +1,46 @@
+import { Sidebar } from "@/Components/v2/sidebar";
+import { Outlet } from "react-router";
+import Stack from "@mui/material/Stack";
+
+// TEMP
+import { useSelector } from "react-redux";
+import type { RootState } from "@/Types/state";
+import { lightTheme, darkTheme } from "@/Utils/Theme/v2Theme";
+import { ThemeProvider, useTheme } from "@mui/material";
+
+const RootLayout = () => {
+ const mode = useSelector((state: RootState) => state.ui.mode);
+ const v2theme = mode === "dark" ? darkTheme : lightTheme;
+ const theme = useTheme();
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default RootLayout;
diff --git a/client/src/Components/v2/sidebar/Logo.tsx b/client/src/Components/v2/sidebar/Logo.tsx
new file mode 100644
index 000000000..131ac03bc
--- /dev/null
+++ b/client/src/Components/v2/sidebar/Logo.tsx
@@ -0,0 +1,60 @@
+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 { toggleSidebar } from "@/Features/UI/uiSlice.js";
+import { useDispatch } from "react-redux";
+import { useTranslation } from "react-i18next";
+import useSidebar from "@/Hooks/useSidebar";
+
+export const Logo = () => {
+ const { t } = useTranslation();
+ const theme = useTheme();
+ const dispatch = useDispatch();
+ const { collapsed } = useSidebar();
+ return (
+ {
+ dispatch(toggleSidebar());
+ }}
+ sx={{ cursor: "pointer" }}
+ >
+
+ C
+
+
+ {" "}
+
+ {t("common.appName")}
+
+
+
+ );
+};
diff --git a/client/src/Components/v2/sidebar/Menu.tsx b/client/src/Components/v2/sidebar/Menu.tsx
new file mode 100644
index 000000000..ad58f4455
--- /dev/null
+++ b/client/src/Components/v2/sidebar/Menu.tsx
@@ -0,0 +1,41 @@
+import { Icon } from "@/Components/v2/design-elements";
+
+import {
+ Globe,
+ Gauge,
+ Link,
+ Bell,
+ FileText,
+ AlertTriangle,
+ Wifi,
+ Wrench,
+ Database,
+ Settings,
+} from "lucide-react";
+
+export const getMenu = (t: Function) => {
+ return [
+ { name: t("menu.uptime"), path: "uptime", icon: },
+ { name: t("menu.pagespeed"), path: "pagespeed", icon: },
+ {
+ name: t("menu.infrastructure"),
+ path: "infrastructure",
+ icon: ,
+ },
+ {
+ name: t("menu.notifications"),
+ path: "notifications",
+ icon: ,
+ },
+ { name: t("menu.checks"), path: "checks", icon: },
+ { name: t("menu.incidents"), path: "incidents", icon: },
+ { name: t("menu.statusPages"), path: "status", icon: },
+ { name: t("menu.maintenance"), path: "maintenance", icon: },
+ { name: t("menu.logs"), path: "logs", icon: },
+ {
+ name: t("menu.settings"),
+ icon: ,
+ path: "settings",
+ },
+ ];
+};
diff --git a/client/src/Components/v2/sidebar/NavItem.tsx b/client/src/Components/v2/sidebar/NavItem.tsx
new file mode 100644
index 000000000..756b10d60
--- /dev/null
+++ b/client/src/Components/v2/sidebar/NavItem.tsx
@@ -0,0 +1,110 @@
+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 "@mui/material/styles";
+import useSidebar from "@/Hooks/useSidebar";
+
+export interface NavData {
+ name: string;
+ icon: React.ReactElement;
+}
+
+export const NavItem = ({
+ item,
+ selected,
+ onClick,
+}: {
+ item: NavData;
+ selected: boolean;
+ onClick: (event: React.MouseEvent) => void;
+}) => {
+ const { collapsed } = useSidebar();
+ const theme = useTheme();
+ const iconStroke = selected ? theme.palette.primary.main : theme.palette.text.secondary;
+
+ const buttonBgColor = selected ? theme.palette.action.selected : "transparent";
+ const buttonBgHoverColor = selected
+ ? theme.palette.action.selected
+ : theme.palette.action.hover;
+ const fontWeight = selected ? 600 : 400;
+ return (
+
+
+
+ {item.icon}
+
+
+
+ {item.name}
+
+
+
+
+ );
+};
diff --git a/client/src/Components/v2/sidebar/index.tsx b/client/src/Components/v2/sidebar/index.tsx
index e69de29bb..10725c6a0 100644
--- a/client/src/Components/v2/sidebar/index.tsx
+++ b/client/src/Components/v2/sidebar/index.tsx
@@ -0,0 +1,69 @@
+import Stack from "@mui/material/Stack";
+import List from "@mui/material/List";
+import { useSidebar } from "@/Hooks/useSidebar.js";
+import { Logo } from "@/Components/v2/sidebar/Logo";
+import { getMenu } from "@/Components/v2/sidebar/Menu";
+import { NavItem } from "@/Components/v2/sidebar/NavItem";
+
+import { useNavigate } from "react-router";
+import { useTranslation } from "react-i18next";
+import { useTheme, useMediaQuery } from "@mui/material";
+import { useDispatch } from "react-redux";
+import { toggleSidebar } from "@/Features/UI/uiSlice";
+
+export const Sidebar = () => {
+ const dispatch = useDispatch();
+ const navigate = useNavigate();
+ const { t } = useTranslation();
+ const { width, transition } = useSidebar();
+ const theme = useTheme();
+ const isSmall = useMediaQuery(theme.breakpoints.down("md"));
+ const menu = getMenu(t);
+
+ return (
+ t.zIndex.drawer : "auto",
+ }}
+ >
+
+
+ {menu.map((item) => {
+ const selected = location.pathname.startsWith(`/${item.path}`);
+ return (
+ {
+ navigate(`/${item.path}`);
+ if (isSmall) {
+ dispatch(toggleSidebar());
+ }
+ }}
+ />
+ );
+ })}
+
+
+ );
+};
diff --git a/client/src/Hooks/useSidebar.js b/client/src/Hooks/useSidebar.js
deleted file mode 100644
index 97724b417..000000000
--- a/client/src/Hooks/useSidebar.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import { useSelector } from "react-redux";
-
-// CSS variable names for sidebar widths
-const SIDEBAR_WIDTH_VAR = "var(--env-var-side-bar-width)";
-const SIDEBAR_COLLAPSED_WIDTH_VAR = "var(--env-var-side-bar-collapsed-width)";
-
-// Transition timing for sidebar width changes
-const SIDEBAR_TRANSITION = "width 650ms cubic-bezier(0.36, -0.01, 0, 0.77)";
-
-/**
- * Hook to get sidebar state and computed width
- * Centralizes sidebar width logic to avoid duplication between Sidebar and HomeLayout
- *
- * @returns {Object} Sidebar state and styles
- * @returns {boolean} collapsed - Whether the sidebar is collapsed
- * @returns {string} width - CSS width value based on collapsed state
- * @returns {string} transition - CSS transition for width changes
- */
-export const useSidebar = () => {
- const collapsed = useSelector((state) => state.ui.sidebar?.collapsed ?? false);
-
- return {
- collapsed,
- width: collapsed ? SIDEBAR_COLLAPSED_WIDTH_VAR : SIDEBAR_WIDTH_VAR,
- transition: SIDEBAR_TRANSITION,
- };
-};
-
-export default useSidebar;
diff --git a/client/src/Hooks/useSidebar.ts b/client/src/Hooks/useSidebar.ts
new file mode 100644
index 000000000..1cf705dd1
--- /dev/null
+++ b/client/src/Hooks/useSidebar.ts
@@ -0,0 +1,25 @@
+import type { RootState } from "@/Types/state";
+import { useSelector } from "react-redux";
+
+// CSS variable names for sidebar widths
+const SIDEBAR_WIDTH_VAR = 250;
+const SIDEBAR_COLLAPSED_WIDTH_VAR = 64;
+
+// Transition timing for sidebar width changes
+const SIDEBAR_TRANSITION = "width 650ms cubic-bezier(0.36, -0.01, 0, 0.77)";
+
+export const useSidebar = () => {
+ const collapsed = useSelector(
+ (state: RootState) => state.ui.sidebar?.collapsed ?? false
+ );
+
+ return {
+ collapsed,
+ collapsedWidth: SIDEBAR_COLLAPSED_WIDTH_VAR,
+ expandedWidth: SIDEBAR_WIDTH_VAR,
+ width: collapsed ? SIDEBAR_COLLAPSED_WIDTH_VAR : SIDEBAR_WIDTH_VAR,
+ transition: SIDEBAR_TRANSITION,
+ };
+};
+
+export default useSidebar;
diff --git a/client/src/Routes/index.jsx b/client/src/Routes/index.jsx
index 07dc1793c..0a66b0cf3 100644
--- a/client/src/Routes/index.jsx
+++ b/client/src/Routes/index.jsx
@@ -4,7 +4,7 @@ import { lightTheme, darkTheme } from "@/Utils/Theme/v2Theme";
import { useSelector } from "react-redux";
import { Navigate, Route, Routes as LibRoutes } from "react-router";
-import HomeLayout from "@/Components/v1/Layouts/HomeLayout";
+import RootLayout from "@/Components/v2/layout/RootLayout";
import NotFound from "@/Pages/NotFound";
// Auth
@@ -67,7 +67,7 @@ const Routes = () => {
path="/"
element={
-
+
}
>