feat: light/dark modes switch immediately with the system theme (#95)

This commit is contained in:
xingo xu 2024-06-06 02:20:05 +09:00 committed by GitHub
parent 3f4e7e9f97
commit c3ac8d9728
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 62 additions and 22 deletions

View File

@ -1,22 +1,52 @@
<script lang="ts"> <script lang="ts">
import type { LIGHT_DARK_MODE } from '@/types/config.ts'
import Icon from "@iconify/svelte" import {
import {i18n} from '@i18n/translation' AUTO_MODE,
DARK_MODE,
LIGHT_MODE,
} from '@constants/constants.ts'
import I18nKey from '@i18n/i18nKey' import I18nKey from '@i18n/i18nKey'
import {setTheme, getStoredTheme} from '../utils/setting-utils.ts' import { i18n } from '@i18n/translation'
import {onMount} from "svelte"; import Icon from '@iconify/svelte'
import {AUTO_MODE, DARK_MODE, LIGHT_MODE} from "@constants/constants.ts"; import {
applyThemeToDocument,
getStoredTheme,
setTheme,
} from '@utils/setting-utils.ts'
import { onMount } from 'svelte'
const seq = [LIGHT_MODE, DARK_MODE, AUTO_MODE] const seq: LIGHT_DARK_MODE[] = [
let mode = AUTO_MODE LIGHT_MODE,
DARK_MODE,
AUTO_MODE,
]
let mode: LIGHT_DARK_MODE = AUTO_MODE
onMount(() => { onMount(() => {
mode = getStoredTheme() mode = getStoredTheme()
const darkModePreference = window.matchMedia(
'(prefers-color-scheme: dark)',
)
const changeThemeWhenSchemeChanged: Parameters<
typeof darkModePreference.addEventListener<'change'>
>[1] = e => {
applyThemeToDocument(mode)
}
darkModePreference.addEventListener(
'change',
changeThemeWhenSchemeChanged,
)
return () => {
darkModePreference.removeEventListener(
'change',
changeThemeWhenSchemeChanged,
)
}
}) })
function switchScheme(newMode: string) { function switchScheme(newMode: LIGHT_DARK_MODE) {
mode = newMode mode = newMode
setTheme(newMode) setTheme(newMode)
} }
function toggleScheme() { function toggleScheme() {

View File

@ -1,3 +1,5 @@
import type { LIGHT_MODE, DARK_MODE, AUTO_MODE } from "@constants/constants"
export type SiteConfig = { export type SiteConfig = {
title: string title: string
subtitle: string subtitle: string
@ -17,7 +19,7 @@ export type SiteConfig = {
} }
export type Favicon = { export type Favicon = {
src: string, src: string
theme?: 'light' | 'dark' theme?: 'light' | 'dark'
sizes?: string sizes?: string
} }
@ -54,3 +56,5 @@ export type LicenseConfig = {
name: string name: string
url: string url: string
} }
export type LIGHT_DARK_MODE = typeof LIGHT_MODE | typeof DARK_MODE | typeof AUTO_MODE

View File

@ -1,4 +1,5 @@
import {AUTO_MODE, DARK_MODE, DEFAULT_THEME, LIGHT_MODE} from "@constants/constants.ts"; import {AUTO_MODE, DARK_MODE, DEFAULT_THEME, LIGHT_MODE} from "@constants/constants.ts";
import type { LIGHT_DARK_MODE } from '@/types/config'
export function getDefaultHue(): number { export function getDefaultHue(): number {
const fallback = '250' const fallback = '250'
@ -20,25 +21,30 @@ export function setHue(hue: number): void {
r.style.setProperty('--hue', hue) r.style.setProperty('--hue', hue)
} }
export function setTheme(theme: string): void {
localStorage.setItem('theme', theme) export function applyThemeToDocument(theme: LIGHT_DARK_MODE) {
switch (theme) { switch (theme) {
case LIGHT_MODE: case LIGHT_MODE:
document.documentElement.classList.remove('dark'); document.documentElement.classList.remove('dark')
break break
case DARK_MODE: case DARK_MODE:
document.documentElement.classList.add('dark'); document.documentElement.classList.add('dark')
break break
case AUTO_MODE: case AUTO_MODE:
if (window.matchMedia('(prefers-color-scheme: dark)').matches) { if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.classList.add('dark'); document.documentElement.classList.add('dark')
} else { } else {
document.documentElement.classList.remove('dark'); document.documentElement.classList.remove('dark')
} }
break break
} }
} }
export function getStoredTheme(): string { export function setTheme(theme: LIGHT_DARK_MODE): void {
return localStorage.getItem('theme') || DEFAULT_THEME localStorage.setItem('theme', theme)
applyThemeToDocument(theme)
}
export function getStoredTheme(): LIGHT_DARK_MODE {
return localStorage.getItem('theme') as LIGHT_DARK_MODE || DEFAULT_THEME
} }