diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index b913071..e3beadf 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,4 +1,5 @@ import './App.css' +import { ThemeProvider } from "@/components/theme-provider" import LatestTemperature from "@/components/latest-temperature" import TemperatureHistory from "@/components/temperature-history" import TemperaturePlot from "@/components/temperature-plot" @@ -9,15 +10,17 @@ import TemperaturePlot from "@/components/temperature-plot" function App() { return ( -
-
- -
- - + +
+
+ +
+ + +
-
-
+ + ) } diff --git a/frontend/src/components/temperature-plot.tsx b/frontend/src/components/temperature-plot.tsx index ab59b46..6d6d6f6 100644 --- a/frontend/src/components/temperature-plot.tsx +++ b/frontend/src/components/temperature-plot.tsx @@ -8,7 +8,7 @@ function TemperaturePlot() { if (error) return

Error: {error.message}

return ( -
+
diff --git a/frontend/src/components/theme-provider.tsx b/frontend/src/components/theme-provider.tsx new file mode 100644 index 0000000..d89a82e --- /dev/null +++ b/frontend/src/components/theme-provider.tsx @@ -0,0 +1,73 @@ +import { createContext, useContext, useEffect, useState } from "react" + +type Theme = "dark" | "light" | "system" + +type ThemeProviderProps = { + children: React.ReactNode + defaultTheme?: Theme + storageKey?: string +} + +type ThemeProviderState = { + theme: Theme + setTheme: (theme: Theme) => void +} + +const initialState: ThemeProviderState = { + theme: "system", + setTheme: () => null, +} + +const ThemeProviderContext = createContext(initialState) + +export function ThemeProvider({ + children, + defaultTheme = "system", + storageKey = "vite-ui-theme", + ...props +}: ThemeProviderProps) { + const [theme, setTheme] = useState( + () => (localStorage.getItem(storageKey) as Theme) || defaultTheme + ) + + useEffect(() => { + const root = window.document.documentElement + + root.classList.remove("light", "dark") + + if (theme === "system") { + const systemTheme = window.matchMedia("(prefers-color-scheme: dark)") + .matches + ? "dark" + : "light" + + root.classList.add(systemTheme) + return + } + + root.classList.add(theme) + }, [theme]) + + const value = { + theme, + setTheme: (theme: Theme) => { + localStorage.setItem(storageKey, theme) + setTheme(theme) + }, + } + + return ( + + {children} + + ) +} + +export const useTheme = () => { + const context = useContext(ThemeProviderContext) + + if (context === undefined) + throw new Error("useTheme must be used within a ThemeProvider") + + return context +}