69 lines
1.5 KiB
TypeScript
69 lines
1.5 KiB
TypeScript
import { create } from "zustand"
|
|
|
|
const themeKey = "theme"
|
|
|
|
export enum Theme {
|
|
Dark = "dark",
|
|
Light = "light",
|
|
}
|
|
export type ThemeState = {
|
|
theme: Theme
|
|
setTheme: (theme: Theme) => void
|
|
}
|
|
|
|
/**
|
|
* Reads site theme setting from local storage
|
|
*/
|
|
function getStoredThemeSetting(): Theme {
|
|
const storedTheme = localStorage.getItem(themeKey)
|
|
|
|
// fix invalid values
|
|
if (
|
|
!storedTheme ||
|
|
(storedTheme != Theme.Dark && storedTheme != Theme.Light)
|
|
) {
|
|
setTheme(Theme.Dark)
|
|
return Theme.Dark
|
|
}
|
|
|
|
return storedTheme
|
|
}
|
|
|
|
/**
|
|
* Sets theme setting without applying them
|
|
*/
|
|
function setTheme(targetTheme: Theme) {
|
|
localStorage.setItem(themeKey, targetTheme)
|
|
}
|
|
|
|
/**
|
|
* Applies tailwind theme using classes based on current theme setting
|
|
*/
|
|
function applyTheme() {
|
|
if (getStoredThemeSetting() === Theme.Dark) {
|
|
document.documentElement.classList.add("dark")
|
|
} else {
|
|
document.documentElement.classList.remove("dark")
|
|
}
|
|
}
|
|
|
|
export const useTheme = create<ThemeState>()((set) => {
|
|
applyTheme()
|
|
|
|
addEventListener("storage", () => {
|
|
setTheme(getStoredThemeSetting())
|
|
applyTheme()
|
|
})
|
|
|
|
return {
|
|
theme: getStoredThemeSetting(),
|
|
setTheme: (themeSetting: Theme) => {
|
|
setTheme(themeSetting)
|
|
applyTheme()
|
|
set((state) => ({
|
|
...state,
|
|
theme: getStoredThemeSetting(),
|
|
}))
|
|
},
|
|
}
|
|
})
|