Last active
May 4, 2020 17:28
-
-
Save gladchinda/2726256c8cd0835e23e5a89e65be272d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState, useCallback } from 'react'; | |
import DarkModeToggleSwitch from './DarkModeToggleSwitch'; | |
import ThemeContext, { DARK_THEME, LIGHT_THEME, DarkMode } from './theme'; | |
export default function App () { | |
const [ dark, setDark ] = useState(DarkMode.getSetting); | |
const theme = dark ? DARK_THEME : LIGHT_THEME; | |
const toggleDarkMode = useCallback(function () { | |
setDark(prevState => { | |
const newState = !prevState; | |
DarkMode.updateSetting(newState); | |
return newState; | |
}); | |
}, []); | |
return <> | |
<div> | |
<DarkModeToggleSwitch on={dark} toggle={toggleDarkMode}/> | |
</div> | |
<ThemeContext.Provider value={theme}> | |
{/* Render rest of app (consume the theme context) */} | |
</ThemeContext.Provider> | |
</> | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { Sun, Moon } from 'react-feather'; | |
export default function DarkModeToggleSwitch ({ on, toggle }) { | |
const props = { | |
type: 'button', | |
role: 'switch', | |
onClick: (typeof toggle === 'function') ? toggle : () => {}, | |
'aria-checked': (on = on === true) | |
}; | |
return <button {...props}>{ on ? <Sun /> : <Moon /> }</button> | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import useTheme from './useTheme'; | |
import ThemeContext from './theme'; | |
export default function App() { | |
const { theme, darkMode, inheritSystem } = useTheme(); | |
return <> | |
{/* Render the color scheme controls widget here */} | |
{/* Use `theme`, `darkMode` and `inheritSystem` as required */} | |
<ThemeContext.Provider value={theme}> | |
{/* Render rest of app (consume the theme context) */} | |
</ThemeContext.Provider> | |
</> | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const mq = window.matchMedia('(prefers-color-scheme: dark)'); | |
console.log(`${mq.matches ? 'dark' : 'light'} mode`); | |
mq.addEventListener('change', function (evt) { | |
console.log(`${evt.matches ? 'dark' : 'light'} mode`); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const mq = window.matchMedia('(prefers-color-scheme: dark)'); | |
const useDarkMode = mq.matches; | |
// logs true if media query matches, otherwise false | |
console.log(useDarkMode); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body {color: #333; background: #fff;} | |
/* Set dark mode styles */ | |
@media (prefers-color-scheme: dark) { | |
body {color: #fff; background: #333;} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { useColorScheme } from 'react-native'; | |
import ThemeContext, { DARK_THEME, LIGHT_THEME } from './theme'; | |
function App () { | |
const scheme = useColorScheme(); | |
const theme = (scheme === 'dark') ? DARK_THEME : LIGHT_THEME; | |
return <> | |
<ThemeContext.Provider value={theme}> | |
{/* Render rest of app (consume the theme context) */} | |
</ThemeContext.Provider> | |
</> | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Appearance } from 'react-native'; | |
const colorScheme = Appearance.getColorScheme(); | |
const useDarkMode = colorScheme === 'dark'; | |
if (useDarkMode) { | |
// Do some dark mode specific stuff here... | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import useColorScheme from './useColorScheme'; | |
import ThemeContext, { DARK_THEME, LIGHT_THEME } from './theme'; | |
function App () { | |
const dark = useColorScheme('dark'); | |
const theme = dark ? DARK_THEME : LIGHT_THEME; | |
return <> | |
<ThemeContext.Provider value={theme}> | |
{/* Render rest of app (consume the theme context) */} | |
</ThemeContext.Provider> | |
</> | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
const DARK_MODE_KEY = 'theme.dark_mode'; | |
const INHERIT_SYSTEM_KEY = 'theme.inherit_system'; | |
const DARK_THEME = { color: '#fff', background: '#333' }; | |
const LIGHT_THEME = { color: '#333', background: '#fff' }; | |
const DarkMode = __themeSettingFactory__(DARK_MODE_KEY); | |
const InheritSystem = __themeSettingFactory__(INHERIT_SYSTEM_KEY); | |
function __themeSettingFactory__(settingKey) { | |
return ({ | |
getSetting: function () { | |
try { | |
return JSON.parse(window.localStorage.getItem(settingKey)) === true; | |
} catch (e) { return false; } | |
}, | |
updateSetting: function (value) { | |
try { | |
window.localStorage.setItem(settingKey, JSON.stringify(value === true)); | |
} catch (e) { } | |
} | |
}); | |
} | |
export { DARK_THEME, LIGHT_THEME, DarkMode, InheritSystem }; | |
export default React.createContext(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
const DARK_MODE_KEY = 'dark_mode'; | |
const DARK_THEME = { color: '#fff', background: '#333' }; | |
const LIGHT_THEME = { color: '#333', background: '#fff' }; | |
const DarkMode = { | |
getSetting: function () { | |
try { | |
return JSON.parse(window.localStorage.getItem(DARK_MODE_KEY)) === true; | |
} catch (e) { return false; } | |
}, | |
updateSetting: function (value) { | |
try { | |
window.localStorage.setItem(DARK_MODE_KEY, JSON.stringify(value === true)); | |
} catch (e) {} | |
} | |
}; | |
export { DARK_THEME, LIGHT_THEME, DarkMode }; | |
export default React.createContext(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useState, useEffect, useRef, useMemo } from 'react'; | |
const COLOR_SCHEMES = ['no-preference', 'dark', 'light']; | |
const DEFAULT_TARGET_COLOR_SCHEME = 'light'; | |
function resolveTargetColorScheme(scheme) { | |
if (!( | |
COLOR_SCHEMES.includes(scheme = String(scheme).toLowerCase()) || | |
scheme === 'no-preference' | |
)) scheme = DEFAULT_TARGET_COLOR_SCHEME; | |
return scheme; | |
} | |
function getCurrentColorScheme() { | |
const QUERIES = {}; | |
return (getCurrentColorScheme = function() { | |
for (let scheme of COLOR_SCHEMES) { | |
const query = QUERIES.hasOwnProperty(scheme) | |
? QUERIES[scheme] | |
: (QUERIES[scheme] = matchMedia(`(prefers-color-scheme: ${scheme})`)); | |
if (query.matches) return { query, scheme }; | |
} | |
})(); | |
} | |
// Define and export the `useColorScheme` hook | |
export default function useColorScheme() {} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export default function useColorScheme(targetColorScheme) { | |
const isMounted = useRef(); | |
const colorScheme = useRef(); | |
const targetScheme = useMemo(() => resolveTargetColorScheme(targetColorScheme), [targetColorScheme]); | |
const [scheme, setColorScheme] = useState(() => { | |
const { scheme } = colorScheme.current = getCurrentColorScheme(); | |
return scheme; | |
}); | |
useEffect(() => { | |
const { query } = colorScheme.current; | |
query.addEventListener('change', schemeChangeHandler); | |
isMounted.current = true; | |
function schemeChangeHandler(evt) { | |
if (!evt.matches) { | |
this.removeEventListener('change', schemeChangeHandler); | |
const { query, scheme } = colorScheme.current = getCurrentColorScheme(); | |
isMounted.current && setColorScheme(scheme); | |
query.addEventListener('change', schemeChangeHandler); | |
} | |
} | |
return () => { | |
const { query } = colorScheme.current; | |
query.removeEventListener('change', schemeChangeHandler); | |
isMounted.current = false; | |
}; | |
}, []); | |
return scheme === targetScheme; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useState, useCallback } from 'react'; | |
import useColorScheme from './useColorScheme'; | |
import { DARK_THEME, LIGHT_THEME, DarkMode, InheritSystem } from './theme'; | |
function __stateToggleFactory__(stateUpdater, settingUpdater) { | |
return function stateToggleFn() { | |
(typeof stateUpdater === 'function') && | |
stateUpdater(prevState => { | |
const newState = !prevState; | |
(typeof settingUpdater === 'function') && settingUpdater(newState); | |
return newState; | |
}); | |
} | |
} | |
export default function useTheme() { | |
const dark = useColorScheme('dark'); | |
const [darkMode, setDarkMode] = useState(DarkMode.getSetting); | |
const [inheritSystem, setInheritSystem] = useState(InheritSystem.getSetting); | |
return { | |
theme: (inheritSystem ? dark : darkMode) ? DARK_THEME : LIGHT_THEME, | |
darkMode: { | |
on: darkMode, | |
toggle: useCallback(__stateToggleFactory__(setDarkMode, DarkMode.updateSetting), []) | |
}, | |
inheritSystem: { | |
on: inheritSystem, | |
toggle: useCallback(__stateToggleFactory__(setInheritSystem, InheritSystem.updateSetting), []) | |
} | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment