From 066d7c7ad2d7a10e8f4f316358e0e98f2bfb31e5 Mon Sep 17 00:00:00 2001 From: lideming Date: Mon, 27 Nov 2023 22:25:24 +0800 Subject: [PATCH] fix: dark theme state for echarts --- .../dashboard/project/hardware/cpugraph.tsx | 1 + neetbox/frontend/src/components/echarts.tsx | 9 +++- .../frontend/src/components/themeSwitcher.tsx | 51 ++++++++++++++++--- neetbox/frontend/src/main.tsx | 11 ++-- 4 files changed, 59 insertions(+), 13 deletions(-) diff --git a/neetbox/frontend/src/components/dashboard/project/hardware/cpugraph.tsx b/neetbox/frontend/src/components/dashboard/project/hardware/cpugraph.tsx index 405385a5..c6fb34e2 100644 --- a/neetbox/frontend/src/components/dashboard/project/hardware/cpugraph.tsx +++ b/neetbox/frontend/src/components/dashboard/project/hardware/cpugraph.tsx @@ -10,6 +10,7 @@ export const CPUGraph = ({ const cpus = hardwareData[0].value.cpus; const initialOption = () => { return { + backgroundColor: 'transparent', animation: false, tooltip: { trigger: "axis", diff --git a/neetbox/frontend/src/components/echarts.tsx b/neetbox/frontend/src/components/echarts.tsx index 60aa9f9b..0a5d91fc 100644 --- a/neetbox/frontend/src/components/echarts.tsx +++ b/neetbox/frontend/src/components/echarts.tsx @@ -1,6 +1,7 @@ import { useRef, useEffect, HTMLAttributes, useState } from "react"; import type * as echarts from "echarts"; import Loading from "./loading"; +import { useTheme } from "./themeSwitcher"; export interface EChartsProps { initialOption: () => echarts.EChartsOption; @@ -14,6 +15,7 @@ export const ECharts = (props: EChartsProps) => { const [echartsModule, setEchartsModule] = useState( null, ); + const { darkMode } = useTheme(); useEffect(() => { import("echarts").then((mod) => setEchartsModule(mod)); @@ -21,7 +23,10 @@ export const ECharts = (props: EChartsProps) => { useEffect(() => { if (echartsModule) { - const chart = echartsModule.init(chartContainerRef.current); + const chart = echartsModule.init( + chartContainerRef.current, + darkMode ? "dark" : null, + ); chart.setOption(props.initialOption()); chartRef.current = chart; @@ -37,7 +42,7 @@ export const ECharts = (props: EChartsProps) => { }; } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [echartsModule]); + }, [echartsModule, darkMode]); useEffect(() => { if (chartRef.current) { diff --git a/neetbox/frontend/src/components/themeSwitcher.tsx b/neetbox/frontend/src/components/themeSwitcher.tsx index 961f3eb5..3d2a7d75 100644 --- a/neetbox/frontend/src/components/themeSwitcher.tsx +++ b/neetbox/frontend/src/components/themeSwitcher.tsx @@ -1,16 +1,53 @@ -import React from "react"; +import React, { + createContext, + useCallback, + useContext, + useEffect, + useState, +} from "react"; import { Button } from "@douyinfe/semi-ui"; +const Context = createContext<{ + darkMode: boolean; + setDarkMode: (val: boolean) => void; +}>(null!); -export default function SwitchColorMode(): React.JSX.Element { - const switchMode = () => { +export function useTheme() { + return useContext(Context); +} + +export function ThemeContextProvider(props: React.PropsWithChildren) { + const [darkMode, setDarkModeState] = useState(false); + + const setDarkMode = useCallback((val) => { + setDarkModeState(val); + localStorage.setItem("neetbox-theme", val ? "dark" : ""); + }, []); + + useEffect(() => { + setDarkModeState(localStorage.getItem("neetbox-theme") === "dark"); + }, []); + + useEffect(() => { const body = document.body; - if (body.hasAttribute("theme-mode")) { - body.removeAttribute("theme-mode"); - } else { + if (darkMode) { body.setAttribute("theme-mode", "dark"); + } else { + body.removeAttribute("theme-mode"); } - }; + }, [darkMode]); + + return ( + + {props.children} + + ); +} +export default function SwitchColorMode(): React.JSX.Element { + const { darkMode, setDarkMode } = useTheme(); + const switchMode = () => { + setDarkMode(!darkMode); + }; return ; } diff --git a/neetbox/frontend/src/main.tsx b/neetbox/frontend/src/main.tsx index 84f71bb4..c657ffe3 100644 --- a/neetbox/frontend/src/main.tsx +++ b/neetbox/frontend/src/main.tsx @@ -6,6 +6,7 @@ import LoginPage from "./pages/login"; import "./index.css"; import Console, { consoleRoutes } from "./pages/console"; import { startBackgroundTasks } from "./services/projects"; +import { ThemeContextProvider } from "./components/themeSwitcher"; const router = createBrowserRouter([ { @@ -36,8 +37,10 @@ function ServiceProvider({ children }: PropsWithChildren) { ReactDOM.createRoot(document.getElementById("root")!).render( - - - - + + + + + + , );