| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- 'use client'
- import { ConfigProvider, theme, App } from 'antd'
- import { useEffect, useState, createContext, useContext } from 'react'
- type ThemeMode = 'light' | 'dark' | 'system'
- interface ThemeContextType {
- mode: ThemeMode
- setMode: (mode: ThemeMode) => void
- isDark: boolean
- }
- const ThemeContext = createContext<ThemeContextType | undefined>(undefined)
- export function useTheme() {
- const context = useContext(ThemeContext)
- if (!context) {
- throw new Error('useTheme must be used within ThemeProvider')
- }
- return context
- }
- export function ThemeProvider({ children }: { children: React.ReactNode }) {
- const [mode, setModeState] = useState<ThemeMode>('system')
- const [isDark, setIsDark] = useState(false)
- const [mounted, setMounted] = useState(false)
- // 初始化:从 localStorage 读取保存的主题设置,并检测系统主题
- useEffect(() => {
- setMounted(true)
- // 从 localStorage 读取保存的主题设置
- const savedMode = localStorage.getItem('theme-mode') as ThemeMode
- if (savedMode && ['light', 'dark', 'system'].includes(savedMode)) {
- setModeState(savedMode)
- }
- // 检测系统主题
- const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
- const currentMode =
- savedMode && ['light', 'dark', 'system'].includes(savedMode)
- ? savedMode
- : 'system'
- if (currentMode === 'system') {
- setIsDark(mediaQuery.matches)
- } else {
- setIsDark(currentMode === 'dark')
- }
- }, [])
- // 检测系统主题变化
- useEffect(() => {
- if (!mounted) return
- const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
- const updateTheme = () => {
- if (mode === 'system') {
- setIsDark(mediaQuery.matches)
- } else {
- setIsDark(mode === 'dark')
- }
- }
- updateTheme()
- // 监听系统主题变化
- mediaQuery.addEventListener('change', updateTheme)
- return () => mediaQuery.removeEventListener('change', updateTheme)
- }, [mode, mounted])
- // 更新 HTML 的 color-scheme 属性
- useEffect(() => {
- document.documentElement.style.colorScheme = isDark ? 'dark' : 'light'
- const meta = document.querySelector('meta[name="color-scheme"]')
- if (meta) {
- meta.setAttribute('content', isDark ? 'dark' : 'light')
- }
- }, [isDark])
- const setMode = (newMode: ThemeMode) => {
- setModeState(newMode)
- localStorage.setItem('theme-mode', newMode)
- }
- return (
- <ThemeContext.Provider value={{ mode, setMode, isDark }}>
- <ConfigProvider
- theme={{
- algorithm: isDark ? theme.darkAlgorithm : theme.defaultAlgorithm,
- }}
- >
- <App>{children}</App>
- </ConfigProvider>
- </ThemeContext.Provider>
- )
- }
|