| 1 | // This file is part of HFS - Copyright 2021-2023, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt |
| 2 | |
| 3 | import { createTheme, useMediaQuery } from '@mui/material' |
| 4 | import { createElement as h, useMemo } from 'react' |
| 5 | import { state, useSnapState } from './state' |
| 6 | import { Btn, BtnProps } from './mui' |
| 7 | import { Brightness4, Brightness7 } from '@mui/icons-material' |
| 8 | |
| 9 | export function useDark() { |
| 10 | return useMediaQuery('(prefers-color-scheme: dark)') |
| 11 | } |
| 12 | |
| 13 | const EMPTY = {} |
| 14 | export function useMyTheme() { |
| 15 | const { darkTheme } = useSnapState() |
| 16 | const detected = useDark() |
| 17 | const lightMode = (darkTheme ?? detected) ? null : EMPTY |
| 18 | return useMemo(() => createTheme({ |
| 19 | palette: lightMode || { |
| 20 | mode: 'dark', |
| 21 | text: { primary: '#bbb', secondary: '#fff6' }, |
| 22 | primary: { main: '#469', light: '#68c' }, |
| 23 | secondary: { main: '#969' }, |
| 24 | }, |
| 25 | typography: { |
| 26 | fontFamily: 'Roboto, "Noto sans", "Segoe UI", "San Francisco", "Helvetica Neue", Arial, sans-serif' |
| 27 | }, |
| 28 | components: { |
| 29 | MuiLink: { |
| 30 | defaultProps: lightMode || { color: 'primary.light' }, // primary.main too dark for dark theme |
| 31 | }, |
| 32 | MuiTextField: { |
| 33 | defaultProps: { variant: 'filled' }, |
| 34 | styleOverrides: lightMode || { |
| 35 | root: { '& label.Mui-focused': { color: '#ccc' } } // our primary.main is too dark for mui's dark theme, and when input element is :-webkit-autofill it will make not enough contrast |
| 36 | } |
| 37 | }, |
| 38 | MuiButton: { |
| 39 | defaultProps: { variant: 'outlined' }, |
| 40 | styleOverrides: lightMode || { |
| 41 | root({ ownerState }) { |
| 42 | return ownerState.color === 'primary' && { |
| 43 | color: ownerState.variant === 'contained' ? '#ddd' : '#68c' |
| 44 | } |
| 45 | } |
| 46 | } |
| 47 | } |
| 48 | } |
| 49 | }), [lightMode]) |
| 50 | } |
| 51 | |
| 52 | export function SwitchThemeBtn(props: BtnProps) { |
| 53 | const { darkTheme } = useSnapState() |
| 54 | const darkDetected = useDark() |
| 55 | const currentlyDark = darkTheme ?? darkDetected |
| 56 | return h(Btn, { |
| 57 | icon: currentlyDark ? Brightness7 : Brightness4, |
| 58 | onClick: () => { |
| 59 | const v = !currentlyDark |
| 60 | return state.darkTheme = darkDetected === v ? undefined : v |
| 61 | }, |
| 62 | ...props, |
| 63 | }, currentlyDark ? "Light theme" : "Dark theme") |
| 64 | } |