diff --git a/DashAI/front/src/components/ResponsiveAppBar.jsx b/DashAI/front/src/components/ResponsiveAppBar.jsx
index 7ac9889d4..3e321957a 100644
--- a/DashAI/front/src/components/ResponsiveAppBar.jsx
+++ b/DashAI/front/src/components/ResponsiveAppBar.jsx
@@ -13,6 +13,9 @@ import MenuItem from "@mui/material/MenuItem";
import { Link as RouterLink, useLocation } from "react-router-dom";
import { useTheme } from "@mui/material/styles";
import HomeIcon from "@mui/icons-material/HomeOutlined";
+import Brightness4Icon from "@mui/icons-material/Brightness4";
+import Brightness7Icon from "@mui/icons-material/Brightness7";
+import { ColorModeContext } from "../contexts/ThemeContext";
const pages = [
{ name: "Datasets", to: "/app/data", disabled: false },
@@ -25,6 +28,7 @@ const pages = [
function ResponsiveAppBar() {
const theme = useTheme();
+ const colorMode = React.useContext(ColorModeContext);
const location = useLocation();
const [anchorElNav, setAnchorElNav] = React.useState(null);
@@ -130,6 +134,27 @@ function ResponsiveAppBar() {
))}
+
+ {/* Theme Toggle Button */}
+
+
+ {theme.palette.mode === "dark" ? (
+
+ ) : (
+
+ )}
+
+
diff --git a/DashAI/front/src/components/explorations/ResultsViewer.jsx b/DashAI/front/src/components/explorations/ResultsViewer.jsx
index 46a7b25c5..3932bbdbb 100644
--- a/DashAI/front/src/components/explorations/ResultsViewer.jsx
+++ b/DashAI/front/src/components/explorations/ResultsViewer.jsx
@@ -4,6 +4,7 @@ import PropTypes from "prop-types";
import { useExplorationsContext } from "./context";
import { Button, Divider, Grid, Typography } from "@mui/material";
+import { useTheme } from "@mui/material/styles";
import { useSnackbar } from "notistack";
import { getExplorersByExplorationId } from "../../api/explorer";
@@ -75,9 +76,12 @@ function ResultsViewer({ updateFlag = false, setUpdateFlag = () => {} }) {
variant="contained"
color={viewMode === viewModes.ALL ? "primary" : "inherit"}
onClick={() => handleChangeViewMode(viewModes.ALL)}
- style={{
- border: "2px solid #00bebb",
- color: viewMode === viewModes.ALL ? "#ffffff" : "#00bebb",
+ sx={{
+ border: `2px solid ${theme.palette.primary.main}`,
+ color:
+ viewMode === viewModes.ALL
+ ? theme.palette.primary.contrastText
+ : theme.palette.primary.main,
borderRadius: "1px",
}}
>
@@ -93,10 +97,12 @@ function ResultsViewer({ updateFlag = false, setUpdateFlag = () => {} }) {
viewMode === viewModes.BY_EXPLORER ? "primary" : "inherit"
}
onClick={() => handleChangeViewMode(viewModes.BY_EXPLORER)}
- style={{
- border: "2px solid #00bebb",
+ sx={{
+ border: `2px solid ${theme.palette.primary.main}`,
color:
- viewMode === viewModes.BY_EXPLORER ? "#ffffff" : "#00bebb",
+ viewMode === viewModes.BY_EXPLORER
+ ? theme.palette.primary.contrastText
+ : theme.palette.primary.main,
borderRadius: "1px",
}}
>
diff --git a/DashAI/front/src/components/generative/Footer.jsx b/DashAI/front/src/components/generative/Footer.jsx
index 6f8cfdfd3..fc66452e3 100644
--- a/DashAI/front/src/components/generative/Footer.jsx
+++ b/DashAI/front/src/components/generative/Footer.jsx
@@ -10,7 +10,7 @@ export default function Footer() {
flexDirection={"column"}
py={2}
>
-
+
setSessionInfoVisible(true)}>
@@ -251,11 +253,11 @@ export default function GenerativeChat({ sessionId, taskName, paramsVersion }) {
width: "8px",
},
"&::-webkit-scrollbar-thumb": {
- backgroundColor: "#555",
+ backgroundColor: theme.palette.ui.border,
borderRadius: "4px",
},
"&::-webkit-scrollbar-thumb:hover": {
- backgroundColor: "#888",
+ backgroundColor: theme.palette.ui.hover,
},
}}
>
diff --git a/DashAI/front/src/components/generative/InfoSessionModal.jsx b/DashAI/front/src/components/generative/InfoSessionModal.jsx
index 53e22f5a6..f77fe415f 100644
--- a/DashAI/front/src/components/generative/InfoSessionModal.jsx
+++ b/DashAI/front/src/components/generative/InfoSessionModal.jsx
@@ -10,8 +10,10 @@ import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TableRow from "@mui/material/TableRow";
+import { useTheme } from "@mui/material/styles";
export default function InfoSessionModal({ sessionData, open, onClose }) {
+ const theme = useTheme();
// Format date for display
const formatDate = (dateString) => {
try {
@@ -91,7 +93,9 @@ export default function InfoSessionModal({ sessionData, open, onClose }) {
/>
Model:{" "}
- {sessionData.model_name}
+
+ {sessionData.model_name}
+
diff --git a/DashAI/front/src/components/generative/MessageContent.jsx b/DashAI/front/src/components/generative/MessageContent.jsx
index 3ed1c8b08..91dba44d6 100644
--- a/DashAI/front/src/components/generative/MessageContent.jsx
+++ b/DashAI/front/src/components/generative/MessageContent.jsx
@@ -9,8 +9,8 @@ export function MessageContent({ messages, isUser, isWaiting }) {
return (
-
+
-
+
{/* Sessions */}
{/* Header */}
-
- Sessions
+
+
+ Sessions
+
Dash
diff --git a/DashAI/front/src/components/generative/SessionBox.jsx b/DashAI/front/src/components/generative/SessionBox.jsx
index a01bdcb22..e6048039c 100644
--- a/DashAI/front/src/components/generative/SessionBox.jsx
+++ b/DashAI/front/src/components/generative/SessionBox.jsx
@@ -21,12 +21,10 @@ export default function SessionBox({
alignItems: "center",
borderRadius: 1,
cursor: isSelected ? "default" : "pointer",
- bgcolor: isSelected ? "rgba(255, 255, 255, 0.05)" : "transparent",
+ bgcolor: isSelected ? "action.selected" : "transparent",
p: 0.5,
"&:hover": {
- backgroundColor: isSelected
- ? "rgba(255, 255, 255, 0.05)"
- : "rgba(255, 255, 255, 0.05)",
+ backgroundColor: isSelected ? "action.selected" : "action.hover",
},
}}
onClick={isSelected ? undefined : onClick}
@@ -42,6 +40,7 @@ export default function SessionBox({
@@ -49,6 +48,7 @@ export default function SessionBox({
diff --git a/DashAI/front/src/components/generative/SessionList.jsx b/DashAI/front/src/components/generative/SessionList.jsx
index ac11dbd3d..0967e1f4f 100644
--- a/DashAI/front/src/components/generative/SessionList.jsx
+++ b/DashAI/front/src/components/generative/SessionList.jsx
@@ -1,4 +1,5 @@
import { Box, Typography, Collapse } from "@mui/material";
+import { useTheme } from "@mui/material/styles";
import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
import KeyboardArrowRightIcon from "@mui/icons-material/KeyboardArrowRight";
import SessionBox from "./SessionBox";
@@ -12,6 +13,7 @@ export default function SessionList({
handleSessionInfo,
toggleSection,
}) {
+ const theme = useTheme();
if (groupedSessions === undefined) {
return (
toggleSection(taskName)}
>
{openSections[taskName] ? (
) : (
)}
-
+
{/* Create new item button */}
@@ -118,7 +118,7 @@ export default function DatasetsNotebooksBar({
/>
-
+
{/* Scrollable content */}
@@ -134,7 +134,7 @@ export default function DatasetsNotebooksBar({
getItemDescription={getDatasetDescription}
/>
-
+
-
+
View mode
-
+
-
+
Processing your dataset...
{
>
{value}
-
+
{label}
diff --git a/DashAI/front/src/components/notebooks/dataset/header/HeaderBox.jsx b/DashAI/front/src/components/notebooks/dataset/header/HeaderBox.jsx
index bf62d436d..3006c9588 100644
--- a/DashAI/front/src/components/notebooks/dataset/header/HeaderBox.jsx
+++ b/DashAI/front/src/components/notebooks/dataset/header/HeaderBox.jsx
@@ -1,7 +1,9 @@
import React from "react";
import { Box, Typography, Tooltip } from "@mui/material";
+import { useTheme } from "@mui/material/styles";
export function HeaderBox({ title, value, IconComponent, iconColor, bgColor }) {
+ const theme = useTheme();
return (
(
-
- {Object.entries(categoricalStats).map(([column, stats]) => (
-
-
- {/* Header */}
-
-
-
- {column}
-
-
+export const CategoricalTab = ({ categoricalStats }) => {
+ const theme = useTheme();
- {/* Summary Stats */}
-
-
-
-
-
-
-
-
-
+ return (
+
+ {Object.entries(categoricalStats).map(([column, stats]) => (
+
+
+ {/* Header */}
+
+
+
+ {column}
+
-
- {/* Charts */}
-
- {/* Value Distribution */}
-
-
- Value Distribution
-
-
-
-
-
-
-
-
-
-
-
+ {/* Summary Stats */}
+
+
+
+
+
+
+
+
+
- {/* Proportion */}
-
-
- Proportion
-
-
-
-
-
- {stats.top_5.map((entry, index) => (
- |
- ))}
-
-
-
-
+ {/* Charts */}
+
+ {/* Value Distribution */}
+
+
+ Value Distribution
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Proportion */}
+
+
+ Proportion
+
+
+
+
+
+ {stats.top_5.map((entry, index) => (
+ |
+ ))}
+
+
+
+
+
-
-
-
- ))}
-
-);
+
+
+ ))}
+
+ );
+};
diff --git a/DashAI/front/src/components/notebooks/dataset/tabs/NumericTab.jsx b/DashAI/front/src/components/notebooks/dataset/tabs/NumericTab.jsx
index ac9682321..8501eb07f 100644
--- a/DashAI/front/src/components/notebooks/dataset/tabs/NumericTab.jsx
+++ b/DashAI/front/src/components/notebooks/dataset/tabs/NumericTab.jsx
@@ -1,142 +1,155 @@
import React from "react";
import { Box, Typography, Card, CardContent, Alert } from "@mui/material";
+import { useTheme } from "@mui/material/styles";
import TrendingUpIcon from "@mui/icons-material/TrendingUp";
import InfoIcon from "@mui/icons-material/Info";
import Plot from "react-plotly.js";
import { StatBox } from "../StatBox";
import { MetricRow } from "../MetricRow";
-export const NumericTab = ({ numericStats }) => (
-
- {Object.entries(numericStats).map(([column, stats]) => (
-
-
- {/* Title */}
-
-
-
- {column}
-
-
+export const NumericTab = ({ numericStats }) => {
+ const theme = useTheme();
- {/* Summary Stats */}
-
-
-
-
-
-
-
-
-
+ return (
+
+ {Object.entries(numericStats).map(([column, stats]) => (
+
+
+ {/* Title */}
+
+
+
+ {column}
+
-
-
+
+ {/* Summary Stats */}
+
+
+
+
+
+
+
+
+
+
+
+
+
-
- {/* Two-column metrics */}
-
- {/* Distribution Metrics */}
-
-
- Distribution Metrics
-
-
-
-
-
-
-
+ {/* Two-column metrics */}
+
+ {/* Distribution Metrics */}
+
+
+ Distribution Metrics
+
+
+
+
+
+
+
+
+
+
+ {/* Shape Indicators */}
+
+
+ Shape Indicators
+
+
+
+
+
+
+
- {/* Shape Indicators */}
-
+ {/* Horizontal Boxplot Visualization */}
+
- Shape Indicators
+ Boxplot
-
-
-
-
-
-
+
-
-
- {/* Horizontal Boxplot Visualization */}
-
-
- Boxplot
-
-
-
- {/* Skewness Warning */}
- {stats.skew > 1 && (
- }
- sx={{ mt: 3 }}
- >
-
- Right-skewed distribution: Consider applying a
- log transformation.
-
-
- )}
-
-
- ))}
-
-);
+ {/* Skewness Warning */}
+ {stats.skew > 1 && (
+ }
+ sx={{ mt: 3 }}
+ >
+
+ Right-skewed distribution: Consider applying
+ a log transformation.
+
+
+ )}
+
+
+ ))}
+
+ );
+};
diff --git a/DashAI/front/src/components/notebooks/dataset/tabs/OverviewTab.jsx b/DashAI/front/src/components/notebooks/dataset/tabs/OverviewTab.jsx
index f7f79df8d..696965a11 100644
--- a/DashAI/front/src/components/notebooks/dataset/tabs/OverviewTab.jsx
+++ b/DashAI/front/src/components/notebooks/dataset/tabs/OverviewTab.jsx
@@ -61,7 +61,7 @@ const OverviewTab = ({
{/* Missing Values Overview */}
-
+
Missing Values Overview
@@ -74,11 +74,12 @@ const OverviewTab = ({
@@ -94,7 +95,7 @@ const OverviewTab = ({
{/* Column Types Distribution */}
-
+
Column Types Distribution
@@ -106,7 +107,7 @@ const OverviewTab = ({
sx={{
p: 2,
textAlign: "center",
- bgcolor: "#363636",
+ bgcolor: theme.palette.ui.disabled,
borderRadius: 2,
}}
>
diff --git a/DashAI/front/src/components/notebooks/dataset/tabs/QualityTab.jsx b/DashAI/front/src/components/notebooks/dataset/tabs/QualityTab.jsx
index a38ec0830..5f681246d 100644
--- a/DashAI/front/src/components/notebooks/dataset/tabs/QualityTab.jsx
+++ b/DashAI/front/src/components/notebooks/dataset/tabs/QualityTab.jsx
@@ -14,7 +14,7 @@ const QualityTab = ({ qualityInfo, totalRows }) => {
{/* Data Quality Summary */}
-
+
Data Quality Summary
@@ -72,7 +72,11 @@ const QualityTab = ({ qualityInfo, totalRows }) => {
{qualityInfo.rows_with_any_nan}
@@ -91,7 +95,11 @@ const QualityTab = ({ qualityInfo, totalRows }) => {
{qualityInfo.rows_with_multiple_nan}
@@ -116,7 +124,7 @@ const QualityTab = ({ qualityInfo, totalRows }) => {
{/* Missing Data by Column */}
-
+
Missing Data by Column
diff --git a/DashAI/front/src/components/notebooks/dataset/tabs/TextTab.jsx b/DashAI/front/src/components/notebooks/dataset/tabs/TextTab.jsx
index bc362df54..503e66f31 100644
--- a/DashAI/front/src/components/notebooks/dataset/tabs/TextTab.jsx
+++ b/DashAI/front/src/components/notebooks/dataset/tabs/TextTab.jsx
@@ -153,11 +153,12 @@ export const TextTab = ({ textStats }) => (
diff --git a/DashAI/front/src/components/notebooks/datasetCreation/PreviewDataset.jsx b/DashAI/front/src/components/notebooks/datasetCreation/PreviewDataset.jsx
index c8f54cd88..954088fd4 100644
--- a/DashAI/front/src/components/notebooks/datasetCreation/PreviewDataset.jsx
+++ b/DashAI/front/src/components/notebooks/datasetCreation/PreviewDataset.jsx
@@ -166,7 +166,7 @@ function PreviewDataset({
fontSize: "1.3rem",
color: "text.secondary",
"&:hover": {
- backgroundColor: "action.hover",
+ backgroundColor: "ui.hover",
},
}}
>
diff --git a/DashAI/front/src/components/notebooks/notebook/DatasetPreviewNotebook.jsx b/DashAI/front/src/components/notebooks/notebook/DatasetPreviewNotebook.jsx
index 37aca3854..862acf525 100644
--- a/DashAI/front/src/components/notebooks/notebook/DatasetPreviewNotebook.jsx
+++ b/DashAI/front/src/components/notebooks/notebook/DatasetPreviewNotebook.jsx
@@ -36,7 +36,7 @@ export default function DatasetPreviewNotebook({
height: "100vh",
}}
>
-
+
Loading...
);
@@ -102,7 +102,7 @@ export default function DatasetPreviewNotebook({
-
+
Loading...
);
diff --git a/DashAI/front/src/components/notebooks/tool/ConfigureToolModal.jsx b/DashAI/front/src/components/notebooks/tool/ConfigureToolModal.jsx
index 882effd5e..fd7ae9f05 100644
--- a/DashAI/front/src/components/notebooks/tool/ConfigureToolModal.jsx
+++ b/DashAI/front/src/components/notebooks/tool/ConfigureToolModal.jsx
@@ -244,7 +244,7 @@ export default function ConfigureToolModal({
height: "6px",
cursor: "row-resize",
backgroundColor: "divider",
- "&:hover": { backgroundColor: "action.hover" },
+ "&:hover": { backgroundColor: "ui.hover" },
zIndex: 2,
}}
/>
diff --git a/DashAI/front/src/components/notebooks/tool/HoverToolInfo.jsx b/DashAI/front/src/components/notebooks/tool/HoverToolInfo.jsx
index f20f1bc14..f83e1d255 100644
--- a/DashAI/front/src/components/notebooks/tool/HoverToolInfo.jsx
+++ b/DashAI/front/src/components/notebooks/tool/HoverToolInfo.jsx
@@ -1,6 +1,7 @@
import React from "react";
import { Box, Typography, Popover, Chip } from "@mui/material";
+import { useTheme } from "@mui/material/styles";
import api from "../../../api/api";
export default function HoverToolInfo({
@@ -8,6 +9,8 @@ export default function HoverToolInfo({
hoveredTool,
handleMouseLeave,
}) {
+ const theme = useTheme();
+
return (
{hoveredTool.display_name}
@@ -66,7 +69,7 @@ export default function HoverToolInfo({
{/* Description */}
{hoveredTool.description}
@@ -78,7 +81,7 @@ export default function HoverToolInfo({
sx={{
bgcolor: hoveredTool.metadata.color,
color: "rgba(255, 255, 255, 1)",
- border: `1px solid rgb(63, 63, 70)`,
+ border: `1px solid ${theme.palette.divider}`,
fontWeight: 500,
}}
/>
diff --git a/DashAI/front/src/components/notebooks/tool/ToolList.jsx b/DashAI/front/src/components/notebooks/tool/ToolList.jsx
index 6b2221bce..02677d5d1 100644
--- a/DashAI/front/src/components/notebooks/tool/ToolList.jsx
+++ b/DashAI/front/src/components/notebooks/tool/ToolList.jsx
@@ -62,7 +62,7 @@ export default function ToolList({ tools, notebook, FormComponent }) {
disableGutters
defaultExpanded
sx={{
- bgcolor: "rgb(31, 31, 31)",
+ bgcolor: theme.palette.ui.box,
borderRadius: 1.5,
overflow: "hidden",
"&:before": { display: "none" },
@@ -88,7 +88,7 @@ export default function ToolList({ tools, notebook, FormComponent }) {
size="small"
label={list.length}
sx={{
- bgcolor: "rgb(43, 43, 43)",
+ bgcolor: theme.palette.ui.disabled,
color: "text.secondary",
height: 20,
}}
diff --git a/DashAI/front/src/components/notebooks/tool/ToolListItem.jsx b/DashAI/front/src/components/notebooks/tool/ToolListItem.jsx
index accda461d..94115b80b 100644
--- a/DashAI/front/src/components/notebooks/tool/ToolListItem.jsx
+++ b/DashAI/front/src/components/notebooks/tool/ToolListItem.jsx
@@ -1,5 +1,6 @@
import React, { useState } from "react";
import { Box, Typography, Chip, Tooltip } from "@mui/material";
+import { useTheme } from "@mui/material/styles";
import HoverToolInfo from "./HoverToolInfo";
import api from "../../../api/api";
import { CategoryIcon } from "./CategoryIcon";
@@ -10,6 +11,7 @@ export default function ToolListItem({
onClick,
...props
}) {
+ const theme = useTheme();
const [anchorEl, setAnchorEl] = useState(null);
const [hoveredTool, setHoveredTool] = useState(null);
@@ -47,16 +49,16 @@ export default function ToolListItem({
slotProps={{
tooltip: {
sx: {
- bgcolor: "rgb(33, 33, 33)",
- color: "rgb(255, 255, 255)",
+ bgcolor: theme.palette.background.paper,
+ color: theme.palette.text.primary,
display: disabled ? "block" : "none",
- border: "1px solid rgb(63, 63, 70)",
+ border: `1px solid ${theme.palette.divider}`,
fontSize: "0.75rem",
maxWidth: 300,
"& .MuiTooltip-arrow": {
- color: "rgb(33, 33, 33)",
+ color: theme.palette.background.paper,
"&::before": {
- border: "1px solid rgb(63, 63, 70)",
+ border: `1px solid ${theme.palette.divider}`,
},
},
},
@@ -75,8 +77,8 @@ export default function ToolListItem({
alignItems: "center",
gap: 1.5,
p: 1.5,
- bgcolor: disabled ? "rgb(32, 32, 32)" : "rgb(44, 44, 44)",
- border: "1px solid rgb(39, 39, 42)",
+ bgcolor: disabled ? "ui.disabled" : "ui.box",
+ border: `1px solid ${theme.palette.ui.border}`,
borderRadius: 1,
cursor: disabled ? "not-allowed" : "pointer",
transition: "all 0.2s",
@@ -84,8 +86,10 @@ export default function ToolListItem({
filter: disabled ? "grayscale(0.6)" : "none",
position: "relative",
"&:hover": {
- bgcolor: disabled ? "rgb(32, 32, 32)" : "rgb(60, 60, 60)",
- borderColor: disabled ? "rgb(39, 39, 42)" : tool.metadata.color,
+ bgcolor: disabled ? "ui.disabled" : theme.palette.action.hover,
+ borderColor: disabled
+ ? theme.palette.ui.border
+ : tool.metadata.color,
transform: disabled ? "none" : "translateX(4px)",
},
"&::after": disabled
@@ -110,15 +114,17 @@ export default function ToolListItem({
width: 36,
height: 36,
borderRadius: 1,
- bgcolor: disabled ? "rgb(50, 50, 50)" : "rgb(63, 63, 70)",
- color: disabled ? "rgb(150, 150, 150)" : "rgb(250, 250, 250)",
+ bgcolor: disabled ? "ui.disabled" : "ui.border",
+ color: disabled ? "text.disabled" : "text.primary",
flexShrink: 0,
}}
>
@@ -135,7 +141,7 @@ export default function ToolListItem({
diff --git a/DashAI/front/src/components/threeSectionLayout/OptionBox.jsx b/DashAI/front/src/components/threeSectionLayout/OptionBox.jsx
index 8a64cbe44..3208b4685 100644
--- a/DashAI/front/src/components/threeSectionLayout/OptionBox.jsx
+++ b/DashAI/front/src/components/threeSectionLayout/OptionBox.jsx
@@ -43,7 +43,7 @@ export default function OptionBox({
justifyContent: matches ? "space-between" : "center",
textAlign: matches ? "left" : "center",
"&:hover": {
- backgroundColor: "#1e1e1e",
+ backgroundColor: theme.palette.action.hover,
},
}}
>
diff --git a/DashAI/front/src/components/threeSectionLayout/SearchBar.jsx b/DashAI/front/src/components/threeSectionLayout/SearchBar.jsx
index f97c9a102..152ed8526 100644
--- a/DashAI/front/src/components/threeSectionLayout/SearchBar.jsx
+++ b/DashAI/front/src/components/threeSectionLayout/SearchBar.jsx
@@ -32,7 +32,7 @@ export default function SearchBar({ placeholder, onChange, value }) {
input: {
startAdornment: (
-
+
),
},
diff --git a/DashAI/front/src/contexts/ThemeContext.jsx b/DashAI/front/src/contexts/ThemeContext.jsx
new file mode 100644
index 000000000..9564da439
--- /dev/null
+++ b/DashAI/front/src/contexts/ThemeContext.jsx
@@ -0,0 +1,35 @@
+import React, { createContext, useState, useMemo, useEffect } from "react";
+import { ThemeProvider, createTheme } from "@mui/material/styles";
+import getTheme from "../styles/theme";
+
+export const ColorModeContext = createContext({ toggleColorMode: () => {} });
+
+export function CustomThemeProvider({ children }) {
+ const [mode, setMode] = useState(() => {
+ // Load saved theme from localStorage or default to dark
+ const savedMode = localStorage.getItem("themeMode");
+ return savedMode || "dark";
+ });
+
+ // Save theme preference to localStorage whenever it changes
+ useEffect(() => {
+ localStorage.setItem("themeMode", mode);
+ }, [mode]);
+
+ const colorMode = useMemo(
+ () => ({
+ toggleColorMode: () => {
+ setMode((prevMode) => (prevMode === "light" ? "dark" : "light"));
+ },
+ }),
+ [],
+ );
+
+ const theme = useMemo(() => createTheme(getTheme(mode)), [mode]);
+
+ return (
+
+ {children}
+
+ );
+}
diff --git a/DashAI/front/src/index.jsx b/DashAI/front/src/index.jsx
index 27362ad2b..f8d698997 100644
--- a/DashAI/front/src/index.jsx
+++ b/DashAI/front/src/index.jsx
@@ -1,17 +1,17 @@
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
-import { createTheme, ThemeProvider } from "@mui/material/styles";
import CssBaseline from "@mui/material/CssBaseline";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
-import theme from "./styles/theme";
import { SnackbarProvider } from "notistack";
+import { CustomThemeProvider } from "./contexts/ThemeContext";
+
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
-
+
-
+
,
);
diff --git a/DashAI/front/src/pages/results/components/MetricsCard.jsx b/DashAI/front/src/pages/results/components/MetricsCard.jsx
index 4da38e3f3..814fb4e5a 100644
--- a/DashAI/front/src/pages/results/components/MetricsCard.jsx
+++ b/DashAI/front/src/pages/results/components/MetricsCard.jsx
@@ -17,10 +17,7 @@ export default function MetricsCard({ title, metrics }) {
key={key}
sx={{ display: "flex", justifyContent: "space-between", mb: 1 }}
>
-
+
{key}:
@@ -29,10 +26,7 @@ export default function MetricsCard({ title, metrics }) {
))
) : (
-
+
No metrics available
)}
diff --git a/DashAI/front/src/pages/results/components/ResultsTabInfo.jsx b/DashAI/front/src/pages/results/components/ResultsTabInfo.jsx
index 812d13242..ed2512abf 100644
--- a/DashAI/front/src/pages/results/components/ResultsTabInfo.jsx
+++ b/DashAI/front/src/pages/results/components/ResultsTabInfo.jsx
@@ -140,10 +140,7 @@ function ResultsTabInfo({ runData, handleRun }) {
{runData.model_name && (
-
+
Model
@@ -153,10 +150,7 @@ function ResultsTabInfo({ runData, handleRun }) {
)}
{runData.start_time && (
-
+
Start Time
@@ -166,10 +160,7 @@ function ResultsTabInfo({ runData, handleRun }) {
)}
{runData.end_time && (
-
+
End Time
@@ -179,10 +170,7 @@ function ResultsTabInfo({ runData, handleRun }) {
)}
{runData.start_time && runData.status !== "Error" && (
-
+
Duration
diff --git a/DashAI/front/src/styles/theme.js b/DashAI/front/src/styles/theme.js
index c0f6e4370..83b9acfb6 100644
--- a/DashAI/front/src/styles/theme.js
+++ b/DashAI/front/src/styles/theme.js
@@ -1,8 +1,8 @@
import QuicksandBoldWoff2 from "./fonts/Quicksand-Bold.woff2";
-const theme = {
+const getTheme = (mode) => ({
palette: {
- mode: "dark",
+ mode,
// PRIMARY - Main application color
// Used in: primary buttons, highlighted icons, links, active elements
@@ -22,31 +22,68 @@ const theme = {
contrastText: "#000",
},
+ // DIVIDER - Divider color
+ // Used in: Divider components, separators
+ divider:
+ mode === "dark" ? "rgba(255, 255, 255, 0.12)" : "rgba(0, 0, 0, 0.12)",
+
// BACKGROUND - Background colors for different surfaces
// Used in: page backgrounds, cards, modals, panels
- background: {
- default: "#2e3037", // Main app background
- paper: "#121212", // Cards and modals background
- box: "#212121", // Boxes and containers (AppBar, sidebars)
- },
+ background:
+ mode === "dark"
+ ? {
+ default: "#2e3037", // Main app background
+ paper: "#121212", // Cards and modals background
+ box: "#212121", // Boxes and containers (AppBar, sidebars)
+ }
+ : {
+ default: "#f5f5f5", // Main app background
+ paper: "#ffffff", // Cards and modals background
+ box: "#fafafa", // Boxes and containers (AppBar, sidebars)
+ },
// TEXT - Text colors
// Used in: Typography components, labels, paragraphs
- text: {
- primary: "#ffffff", // Primary text (titles, important labels)
- secondary: "#b0b0b0", // Secondary text (descriptions, subtitles)
- },
+ text:
+ mode === "dark"
+ ? {
+ primary: "#ffffff", // Primary text (titles, important labels)
+ secondary: "#b0b0b0", // Secondary text (descriptions, subtitles)
+ disabled: "#757575", // Disabled text
+ }
+ : {
+ primary: "#1a1a1a", // Primary text (titles, important labels)
+ secondary: "#666666", // Secondary text (descriptions, subtitles)
+ disabled: "#9e9e9e", // Disabled text
+ },
+
+ // ACTION - Interactive states
+ // Used in: hover states, selected items, disabled states, focus indicators
+ action:
+ mode === "dark"
+ ? {
+ hover: "rgba(255, 255, 255, 0.08)", // Hover state for interactive elements
+ selected: "rgba(255, 255, 255, 0.16)", // Selected state for items
+ disabled: "rgba(255, 255, 255, 0.3)", // Disabled state opacity
+ disabledBackground: "rgba(255, 255, 255, 0.12)", // Disabled background
+ }
+ : {
+ hover: "rgba(0, 0, 0, 0.04)", // Hover state for interactive elements
+ selected: "rgba(0, 0, 0, 0.08)", // Selected state for items
+ disabled: "rgba(0, 0, 0, 0.26)", // Disabled state opacity
+ disabledBackground: "rgba(0, 0, 0, 0.12)", // Disabled background
+ },
// ERROR - Error states
// Used in: error messages, failed validations, critical alerts
error: {
- main: "#ff8383",
+ main: mode === "dark" ? "#ff8383" : "#d32f2f",
},
// WARNING - Warning states
// Used in: warning alerts, pending states requiring attention
warning: {
- main: "#f1ae61",
+ main: mode === "dark" ? "#f1ae61" : "#ed6c02",
},
// SUCCESS - Success states
@@ -66,6 +103,7 @@ const theme = {
// ACCENT - Custom accent colors
// Used in: elements requiring emphasis, special details
accent: {
+ main: "#16FFFF", // Main accent color (cyan)
cyan: "#16FFFF", // For highlights
teal: "#00BEBB", // For featured elements
},
@@ -73,11 +111,11 @@ const theme = {
// STATUS - Experiment/job states
// Used in: status badges, progress indicators in experiments and runs
status: {
- notStarted: "#626262", // Experiment not started
+ notStarted: mode === "dark" ? "#626262" : "#9e9e9e", // Experiment not started
started: "#3e68ffff", // Experiment running
finished: "#43A047", // Experiment completed successfully
delivered: "#3e68ffff", // Results delivered
- error: "#A70909", // Experiment error
+ error: mode === "dark" ? "#A70909" : "#c62828", // Experiment error
},
// DATATYPE - Colors for data types in columns
@@ -103,18 +141,36 @@ const theme = {
// UI - Interface elements and borders
// Used in: borders, dividers, scrollbars, hover states
- ui: {
- border: "#333", // Standard border
- borderLight: "#444", // Lighter border
- borderDark: "#252836", // Darker border
- panelDark: "#2C2C2C", // Dark panel
- panelMedium: "#363636", // Medium panel
- panelLight: "#2F2F2F", // Light panel
- scrollbar: "#374151", // Scrollbar color
- scrollbarHover: "#4B5563", // Scrollbar on hover
- hover: "rgba(255, 255, 255, 0.05)", // Element hover state
- divider: "rgba(255, 255, 255, 0.15)", // Dividers and separators
- },
+ ui:
+ mode === "dark"
+ ? {
+ border: "#333", // Standard border
+ borderLight: "#444", // Lighter border
+ borderDark: "#252836", // Darker border
+ panelDark: "#2C2C2C", // Dark panel
+ panelMedium: "#363636", // Medium panel
+ panelLight: "#2F2F2F", // Light panel
+ scrollbar: "#374151", // Scrollbar color
+ scrollbarHover: "#4B5563", // Scrollbar on hover
+ hover: "rgba(255, 255, 255, 0.05)", // Element hover state
+ divider: "rgba(255, 255, 255, 0.15)", // Dividers and separators
+ box: "#212121", // Boxes and containers background
+ disabled: "#2C2C2C", // Disabled elements background
+ }
+ : {
+ border: "#e0e0e0", // Standard border
+ borderLight: "#f0f0f0", // Lighter border
+ borderDark: "#d0d0d0", // Darker border
+ panelDark: "#f5f5f5", // Light panel
+ panelMedium: "#fafafa", // Medium panel
+ panelLight: "#ffffff", // Lightest panel
+ scrollbar: "#bdbdbd", // Scrollbar color
+ scrollbarHover: "#9e9e9e", // Scrollbar on hover
+ hover: "rgba(0, 0, 0, 0.04)", // Element hover state
+ divider: "rgba(0, 0, 0, 0.12)", // Dividers and separators
+ box: "#fafafa", // Boxes and containers background
+ disabled: "#f5f5f5", // Disabled elements background
+ },
},
typography: {
fontFamily: "Quicksand-Bold",
@@ -142,11 +198,11 @@ const theme = {
::-webkit-scrollbar-thumb {
-webkit-border-radius: 10px;
border-radius: 10px;
- background: rgba(0, 0, 0, 0.8);
+ background: ${mode === "dark" ? "rgba(0, 0, 0, 0.8)" : "rgba(0, 0, 0, 0.3)"};
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5);
}
::-webkit-scrollbar-thumb:window-inactive {
- background: rgba(0,0,0,0.4);
+ background: ${mode === "dark" ? "rgba(0,0,0,0.4)" : "rgba(0,0,0,0.2)"};
}
`,
},
@@ -168,6 +224,6 @@ const theme = {
},
},
},
-};
+});
-export default theme;
+export default getTheme;