feat: support primary color customization
This commit is contained in:
parent
b17846f264
commit
28dad7373f
21 changed files with 644 additions and 43 deletions
|
|
@ -1,36 +1,36 @@
|
|||
import { PRIMARY_COLORS, StorageKey, TPrimaryColor } from '@/constants'
|
||||
import storage from '@/services/local-storage.service'
|
||||
import { TTheme, TThemeSetting } from '@/types'
|
||||
import { createContext, useContext, useEffect, useState } from 'react'
|
||||
|
||||
type ThemeProviderState = {
|
||||
themeSetting: TThemeSetting
|
||||
setThemeSetting: (themeSetting: TThemeSetting) => Promise<void>
|
||||
}
|
||||
|
||||
function getSystemTheme() {
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
|
||||
setThemeSetting: (themeSetting: TThemeSetting) => void
|
||||
primaryColor: TPrimaryColor
|
||||
setPrimaryColor: (color: TPrimaryColor) => void
|
||||
}
|
||||
|
||||
const ThemeProviderContext = createContext<ThemeProviderState | undefined>(undefined)
|
||||
|
||||
const updateCSSVariables = (color: TPrimaryColor, currentTheme: TTheme) => {
|
||||
const root = window.document.documentElement
|
||||
const colorConfig = PRIMARY_COLORS[color] ?? PRIMARY_COLORS.DEFAULT
|
||||
|
||||
const config = currentTheme === 'light' ? colorConfig.light : colorConfig.dark
|
||||
|
||||
root.style.setProperty('--primary', config.primary)
|
||||
root.style.setProperty('--primary-hover', config['primary-hover'])
|
||||
root.style.setProperty('--primary-foreground', config['primary-foreground'])
|
||||
}
|
||||
|
||||
export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
||||
const [themeSetting, setThemeSetting] = useState<TThemeSetting>(
|
||||
(localStorage.getItem('themeSetting') as TThemeSetting | null) ?? 'system'
|
||||
(localStorage.getItem(StorageKey.THEME_SETTING) as TThemeSetting) ?? 'system'
|
||||
)
|
||||
const [theme, setTheme] = useState<TTheme>('light')
|
||||
|
||||
useEffect(() => {
|
||||
const init = async () => {
|
||||
const themeSetting = storage.getThemeSetting()
|
||||
if (themeSetting === 'system') {
|
||||
setTheme(getSystemTheme())
|
||||
return
|
||||
}
|
||||
setTheme(themeSetting)
|
||||
}
|
||||
|
||||
init()
|
||||
}, [])
|
||||
const [primaryColor, setPrimaryColor] = useState<TPrimaryColor>(
|
||||
(localStorage.getItem(StorageKey.PRIMARY_COLOR) as TPrimaryColor) ?? 'DEFAULT'
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (themeSetting !== 'system') {
|
||||
|
|
@ -65,16 +65,27 @@ export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
|||
updateTheme()
|
||||
}, [theme])
|
||||
|
||||
const updateThemeSetting = async (themeSetting: TThemeSetting) => {
|
||||
useEffect(() => {
|
||||
updateCSSVariables(primaryColor, theme)
|
||||
}, [theme, primaryColor])
|
||||
|
||||
const updateThemeSetting = (themeSetting: TThemeSetting) => {
|
||||
storage.setThemeSetting(themeSetting)
|
||||
setThemeSetting(themeSetting)
|
||||
}
|
||||
|
||||
const updatePrimaryColor = (color: TPrimaryColor) => {
|
||||
storage.setPrimaryColor(color)
|
||||
setPrimaryColor(color)
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeProviderContext.Provider
|
||||
value={{
|
||||
themeSetting: themeSetting,
|
||||
setThemeSetting: updateThemeSetting
|
||||
themeSetting,
|
||||
setThemeSetting: updateThemeSetting,
|
||||
primaryColor,
|
||||
setPrimaryColor: updatePrimaryColor
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue