mirror of
https://github.com/xmanrui/OpenClaw-bot-review.git
synced 2026-08-14 00:47:49 +00:00
65 lines
1.7 KiB
TypeScript
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>
|
|
);
|
|
}
|