Path: blob/trunk/javascript/grid-ui/src/contexts/ThemeContext.tsx
1989 views
// Licensed to the Software Freedom Conservancy (SFC) under one1// or more contributor license agreements. See the NOTICE file2// distributed with this work for additional information3// regarding copyright ownership. The SFC licenses this file4// to you under the Apache License, Version 2.0 (the5// "License"); you may not use this file except in compliance6// with the License. You may obtain a copy of the License at7//8// http://www.apache.org/licenses/LICENSE-2.09//10// Unless required by applicable law or agreed to in writing,11// software distributed under the License is distributed on an12// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY13// KIND, either express or implied. See the License for the14// specific language governing permissions and limitations15// under the License.161718import React, { createContext, useContext, useState, useEffect } from 'react'19import { ThemeProvider } from '@mui/material/styles'20import { CssBaseline } from '@mui/material'21import { lightTheme, darkTheme } from '../theme/themes'2223type ThemeMode = 'light' | 'dark' | 'system'2425const ThemeContext = createContext<{26themeMode: ThemeMode27setThemeMode: (mode: ThemeMode) => void28}>({29themeMode: 'system',30setThemeMode: () => {}31})3233export const useTheme = () => useContext(ThemeContext)3435export const CustomThemeProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {36const [themeMode, setThemeMode] = useState<ThemeMode>('system')37const [systemPrefersDark, setSystemPrefersDark] = useState(false)3839useEffect(() => {40if (typeof window !== 'undefined' && window.localStorage) {41const saved = localStorage.getItem('theme-mode') as ThemeMode42if (saved) setThemeMode(saved)43}44if (typeof window !== 'undefined' && window.matchMedia) {45setSystemPrefersDark(window.matchMedia('(prefers-color-scheme: dark)').matches)46}47}, [])4849useEffect(() => {50if (typeof window !== 'undefined' && window.localStorage) {51localStorage.setItem('theme-mode', themeMode)52}53}, [themeMode])5455useEffect(() => {56if (typeof window !== 'undefined' && window.matchMedia) {57const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')58const handler = (e: MediaQueryListEvent) => setSystemPrefersDark(e.matches)59mediaQuery.addEventListener('change', handler)60return () => mediaQuery.removeEventListener('change', handler)61}62}, [])6364const isDark = themeMode === 'dark' || (themeMode === 'system' && systemPrefersDark)65const currentTheme = isDark ? darkTheme : lightTheme6667return (68<ThemeContext.Provider value={{ themeMode, setThemeMode }}>69<ThemeProvider theme={currentTheme}>70<CssBaseline />71{children}72</ThemeProvider>73</ThemeContext.Provider>74)75}767778