diff --git a/package.json b/package.json index 5739eb1..6ccd618 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "physicshub", "homepage": "https://physicshub.github.io", "private": true, - "version": "2.2.1", + "version": "2.3.0", "type": "module", "scripts": { "dev": "vite", diff --git a/src/components/Theme.tsx b/src/components/Theme.tsx index dce1420..a332c8d 100644 --- a/src/components/Theme.tsx +++ b/src/components/Theme.tsx @@ -1,8 +1,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faSun, faMoon } from '@fortawesome/free-solid-svg-icons'; +import { faSun, faMoon, faCircleHalfStroke } from '@fortawesome/free-solid-svg-icons'; interface Props { - mode: 'light' | 'dark'; + mode: 'light' | 'dark' | 'system'; onToggle: () => void; } @@ -13,7 +13,11 @@ export function Theme({ mode, onToggle }: Props) { onClick={onToggle} aria-label="Toggle theme" > - + ); } diff --git a/src/hooks/useTheme.tsx b/src/hooks/useTheme.tsx index 5beeb04..7550829 100644 --- a/src/hooks/useTheme.tsx +++ b/src/hooks/useTheme.tsx @@ -1,14 +1,36 @@ import { useState, useEffect, useCallback } from 'react'; -export function useTheme(defaultMode: 'light' | 'dark' = 'dark') { +export function useTheme(defaultMode: 'light' | 'dark' | 'system' = 'system') { const [mode, setMode] = useState(defaultMode); - useEffect(() => { - document.body.dataset.theme = mode; - }, [mode]); + const getSystemTheme = () => { + return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' + } + + useEffect(() => { + let actualTheme = mode; + if(mode === 'system'){ + actualTheme = getSystemTheme(); + } + document.body.dataset.theme = actualTheme; + if(mode === 'system'){ + const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); + + const handleChange = () => { + document.body.dataset.theme = getSystemTheme(); + }; + + mediaQuery.addEventListener('change', handleChange); + return ()=> mediaQuery.removeEventListener('change', handleChange); + } +}, [mode]); const toggleMode = useCallback( - () => setMode(prev => (prev === 'dark' ? 'light' : 'dark')), + () => setMode(prev => { + if(prev === 'dark') return 'light'; + if(prev === 'light') return 'system'; + return 'dark'; + }), [] );