Files
OpenClaw-bot-review/lib/theme.tsx
T

65 lines
1.7 KiB
TypeScript

"use client";
import { createContext, useContext, useState, useCallback, useEffect, ReactNode } from "react";
import { useI18n } from "@/lib/i18n";
export type Theme = "dark" | "light";
interface ThemeContextType {
theme: Theme;
setTheme: (t: Theme) => void;
toggleTheme: () => void;
}
const ThemeContext = createContext<ThemeContextType>({
theme: "dark",
setTheme: () => {},
toggleTheme: () => {},
});
export function ThemeProvider({ children }: { children: ReactNode }) {
const [theme, setThemeState] = useState<Theme>("dark");
useEffect(() => {
const saved = localStorage.getItem("theme") as Theme;
if (saved === "light" || saved === "dark") {
setThemeState(saved);
document.documentElement.setAttribute("data-theme", saved);
}
}, []);
const setTheme = useCallback((t: Theme) => {
setThemeState(t);
document.documentElement.setAttribute("data-theme", t);
localStorage.setItem("theme", t);
}, []);
const toggleTheme = useCallback(() => {
setTheme(theme === "dark" ? "light" : "dark");
}, [theme, setTheme]);
return (
<ThemeContext.Provider value={{ theme, setTheme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
export function useTheme() {
return useContext(ThemeContext);
}
export function ThemeSwitcher() {
const { theme, toggleTheme } = useTheme();
const { t } = useI18n();
return (
<button
onClick={toggleTheme}
className="px-2 py-1.5 rounded-lg bg-[var(--bg)] border border-[var(--border)] text-sm hover:border-[var(--accent)] transition cursor-pointer"
title={theme === "dark" ? t("theme.switchToLight") : t("theme.switchToDark")}
>
{theme === "dark" ? "☀️" : "🌙"}
</button>
);
}