mirror of
https://github.com/woodchen-ink/nezha-dash-v1.git
synced 2025-07-18 01:21:56 +08:00
移除主题切换相关组件,简化主题管理逻辑,默认设置为暗黑模式,提升代码整洁性和用户体验。
This commit is contained in:
parent
9090b407cc
commit
3958b3b35c
49
index.html
49
index.html
@ -3,29 +3,20 @@
|
||||
<head>
|
||||
<script>
|
||||
// 在页面渲染前就执行主题初始化
|
||||
try {
|
||||
const storageKey = "vite-ui-theme"
|
||||
let theme = localStorage.getItem(storageKey)
|
||||
if (theme === "system" || !theme) {
|
||||
theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"
|
||||
}
|
||||
document.documentElement.classList.add(theme)
|
||||
} catch (e) {
|
||||
document.documentElement.classList.add("light")
|
||||
}
|
||||
document.documentElement.classList.add("dark")
|
||||
|
||||
// 全局配置变量
|
||||
window.ShowServerDetails = true; // 是否显示服务器详细信息
|
||||
</script>
|
||||
<style>
|
||||
/* Prevent FOUC in Safari */
|
||||
html:not(.dark):not(.light) * {
|
||||
html:not(.dark) * {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
:root {
|
||||
color-scheme: light;
|
||||
--bg: #ffffff;
|
||||
color-scheme: dark;
|
||||
--bg: #242424;
|
||||
}
|
||||
|
||||
html.dark {
|
||||
@ -33,11 +24,6 @@
|
||||
--bg: #242424;
|
||||
}
|
||||
|
||||
html.light {
|
||||
color-scheme: light;
|
||||
--bg: #ffffff;
|
||||
}
|
||||
|
||||
html {
|
||||
background-color: var(--bg) !important;
|
||||
}
|
||||
@ -67,31 +53,10 @@
|
||||
</style>
|
||||
<script>
|
||||
;(function () {
|
||||
const storageKey = "vite-ui-theme"
|
||||
const theme = localStorage.getItem(storageKey) || "system"
|
||||
const root = document.documentElement
|
||||
|
||||
function updateThemeColor(isDark) {
|
||||
const themeColor = isDark ? "#242424" : "#fafafa"
|
||||
document.querySelector('meta[name="theme-color"]')?.setAttribute("content", themeColor)
|
||||
}
|
||||
|
||||
function setTheme(newTheme) {
|
||||
root.classList.remove("light", "dark")
|
||||
root.classList.add(newTheme)
|
||||
updateThemeColor(newTheme === "dark")
|
||||
}
|
||||
|
||||
if (theme === "system") {
|
||||
const systemTheme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"
|
||||
setTheme(systemTheme)
|
||||
|
||||
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (e) => {
|
||||
setTheme(e.matches ? "dark" : "light")
|
||||
})
|
||||
} else {
|
||||
setTheme(theme)
|
||||
}
|
||||
root.classList.remove("light")
|
||||
root.classList.add("dark")
|
||||
document.querySelector('meta[name="theme-color"]')?.setAttribute("content", "#242424")
|
||||
|
||||
// Add loaded class after React has mounted
|
||||
window.addEventListener("load", () => {
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { ModeToggle } from "@/components/ThemeSwitcher"
|
||||
import { Separator } from "@/components/ui/separator"
|
||||
import { Skeleton } from "@/components/ui/skeleton"
|
||||
import { useBackground } from "@/hooks/use-background"
|
||||
@ -102,7 +101,6 @@ function Header() {
|
||||
<Links />
|
||||
<DashboardLink />
|
||||
</div>
|
||||
<ModeToggle />
|
||||
{(customBackgroundImage || sessionStorage.getItem("savedBackgroundImage")) && (
|
||||
<Button
|
||||
variant="outline"
|
||||
|
@ -1,39 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { useTheme } from "@/hooks/use-theme"
|
||||
import { useEffect } from "react"
|
||||
|
||||
export function ThemeColorManager() {
|
||||
const { theme } = useTheme()
|
||||
|
||||
useEffect(() => {
|
||||
const updateThemeColor = () => {
|
||||
const currentTheme = theme
|
||||
const meta = document.querySelector('meta[name="theme-color"]')
|
||||
|
||||
if (!meta) {
|
||||
const newMeta = document.createElement("meta")
|
||||
newMeta.name = "theme-color"
|
||||
document.head.appendChild(newMeta)
|
||||
}
|
||||
|
||||
const themeColor =
|
||||
currentTheme === "dark"
|
||||
? "hsl(30 15% 8%)" // 深色模式背景色
|
||||
: "hsl(0 0% 98%)" // 浅色模式背景色
|
||||
|
||||
document.querySelector('meta[name="theme-color"]')?.setAttribute("content", themeColor)
|
||||
}
|
||||
|
||||
// Update on mount and theme change
|
||||
updateThemeColor()
|
||||
|
||||
// Listen for system theme changes
|
||||
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)")
|
||||
mediaQuery.addEventListener("change", updateThemeColor)
|
||||
|
||||
return () => mediaQuery.removeEventListener("change", updateThemeColor)
|
||||
}, [theme])
|
||||
|
||||
return null
|
||||
}
|
@ -1,11 +1,9 @@
|
||||
import { ReactNode, createContext, useEffect, useState } from "react"
|
||||
import { ReactNode, createContext } from "react"
|
||||
|
||||
export type Theme = "dark" | "light" | "system"
|
||||
export type Theme = "dark"
|
||||
|
||||
type ThemeProviderProps = {
|
||||
children: ReactNode
|
||||
defaultTheme?: Theme
|
||||
storageKey?: string
|
||||
}
|
||||
|
||||
type ThemeProviderState = {
|
||||
@ -14,40 +12,22 @@ type ThemeProviderState = {
|
||||
}
|
||||
|
||||
const initialState: ThemeProviderState = {
|
||||
theme: "system",
|
||||
theme: "dark",
|
||||
setTheme: () => null,
|
||||
}
|
||||
|
||||
const ThemeProviderContext = createContext<ThemeProviderState>(initialState)
|
||||
|
||||
export function ThemeProvider({ children, storageKey = "vite-ui-theme" }: ThemeProviderProps) {
|
||||
const [theme, setTheme] = useState<Theme>(() => (localStorage.getItem(storageKey) as Theme) || "system")
|
||||
export function ThemeProvider({ children }: ThemeProviderProps) {
|
||||
const root = window.document.documentElement
|
||||
root.classList.remove("light")
|
||||
root.classList.add("dark")
|
||||
const themeColor = "hsl(30 15% 8%)"
|
||||
document.querySelector('meta[name="theme-color"]')?.setAttribute("content", themeColor)
|
||||
|
||||
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)
|
||||
const themeColor = systemTheme === "dark" ? "hsl(30 15% 8%)" : "hsl(0 0% 98%)"
|
||||
document.querySelector('meta[name="theme-color"]')?.setAttribute("content", themeColor)
|
||||
return
|
||||
}
|
||||
|
||||
root.classList.add(theme)
|
||||
const themeColor = theme === "dark" ? "hsl(30 15% 8%)" : "hsl(0 0% 98%)"
|
||||
document.querySelector('meta[name="theme-color"]')?.setAttribute("content", themeColor)
|
||||
}, [theme])
|
||||
|
||||
const value = {
|
||||
theme,
|
||||
setTheme: (theme: Theme) => {
|
||||
localStorage.setItem(storageKey, theme)
|
||||
setTheme(theme)
|
||||
},
|
||||
const value: ThemeProviderState = {
|
||||
theme: "dark",
|
||||
setTheme: () => null,
|
||||
}
|
||||
|
||||
return <ThemeProviderContext.Provider value={value}>{children}</ThemeProviderContext.Provider>
|
||||
|
@ -1,53 +0,0 @@
|
||||
import { Theme } from "@/components/ThemeProvider"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { CheckCircleIcon } from "@heroicons/react/20/solid"
|
||||
import { Moon, Sun } from "lucide-react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
||||
import { useTheme } from "../hooks/use-theme"
|
||||
|
||||
export function ModeToggle() {
|
||||
const { t } = useTranslation()
|
||||
const { setTheme, theme } = useTheme()
|
||||
|
||||
const customBackgroundImage = (window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
||||
|
||||
const handleSelect = (e: Event, newTheme: Theme) => {
|
||||
e.preventDefault()
|
||||
setTheme(newTheme)
|
||||
}
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className={cn("rounded-full px-[9px] bg-white dark:bg-black", {
|
||||
"bg-white/70 dark:bg-black/70": customBackgroundImage,
|
||||
})}
|
||||
>
|
||||
<Sun className="h-4 w-4 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
||||
<Moon className="absolute h-4 w-4 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
||||
<span className="sr-only">Toggle theme</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="flex flex-col gap-0.5" align="end">
|
||||
<DropdownMenuItem className={cn({ "gap-3 bg-muted": theme === "light" })} onSelect={(e) => handleSelect(e, "light")}>
|
||||
{t("theme.light")}
|
||||
{theme === "light" && <CheckCircleIcon className="size-4" />}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem className={cn({ "gap-3 bg-muted": theme === "dark" })} onSelect={(e) => handleSelect(e, "dark")}>
|
||||
{t("theme.dark")}
|
||||
{theme === "dark" && <CheckCircleIcon className="size-4" />}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem className={cn({ "gap-3 bg-muted": theme === "system" })} onSelect={(e) => handleSelect(e, "system")}>
|
||||
{t("theme.system")}
|
||||
{theme === "system" && <CheckCircleIcon className="size-4" />}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)
|
||||
}
|
@ -4,7 +4,6 @@ import ReactDOM from "react-dom/client"
|
||||
import { Toaster } from "sonner"
|
||||
|
||||
import App from "./App"
|
||||
import { ThemeColorManager } from "./components/ThemeColorManager"
|
||||
import { ThemeProvider } from "./components/ThemeProvider"
|
||||
import { MotionProvider } from "./components/motion/motion-provider"
|
||||
import { SortProvider } from "./context/sort-provider"
|
||||
@ -18,8 +17,7 @@ const queryClient = new QueryClient()
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")!).render(
|
||||
<MotionProvider>
|
||||
<ThemeProvider storageKey="vite-ui-theme">
|
||||
<ThemeColorManager />
|
||||
<ThemeProvider>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<WebSocketProvider url="/api/v1/ws/server">
|
||||
<StatusProvider>
|
||||
|
Loading…
x
Reference in New Issue
Block a user