feat(webui): add initial webui with websocket chat flow
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
|
||||
type Theme = "light" | "dark";
|
||||
const STORAGE_KEY = "nanobot-webui.theme";
|
||||
|
||||
function readStored(): Theme | null {
|
||||
try {
|
||||
const v = localStorage.getItem(STORAGE_KEY);
|
||||
return v === "light" || v === "dark" ? v : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function applyTheme(theme: Theme): void {
|
||||
const root = document.documentElement;
|
||||
if (theme === "dark") root.classList.add("dark");
|
||||
else root.classList.remove("dark");
|
||||
}
|
||||
|
||||
export function useTheme(): { theme: Theme; toggle: () => void; setTheme: (t: Theme) => void } {
|
||||
const [theme, setThemeState] = useState<Theme>(() => {
|
||||
const stored = readStored();
|
||||
if (stored) return stored;
|
||||
if (typeof window !== "undefined" && window.matchMedia) {
|
||||
return window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||
? "dark"
|
||||
: "light";
|
||||
}
|
||||
return "light";
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
applyTheme(theme);
|
||||
try {
|
||||
localStorage.setItem(STORAGE_KEY, theme);
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}, [theme]);
|
||||
|
||||
const setTheme = useCallback((t: Theme) => setThemeState(t), []);
|
||||
const toggle = useCallback(
|
||||
() => setThemeState((t) => (t === "dark" ? "light" : "dark")),
|
||||
[],
|
||||
);
|
||||
return { theme, toggle, setTheme };
|
||||
}
|
||||
Reference in New Issue
Block a user