1
0
mirror of https://github.com/kremalicious/portfolio.git synced 2024-11-14 17:15:15 +01:00

custom useDarkMode hook

This commit is contained in:
Matthias Kretschmann 2021-03-13 03:35:50 +01:00
parent 15b5006df4
commit 487461518a
Signed by: m
GPG Key ID: 606EEEF3C479A91F
7 changed files with 79 additions and 28211 deletions

View File

@ -74,11 +74,12 @@ If you want to know how, have a look at the respective components:
### 💅 Theme switcher ### 💅 Theme switcher
Includes a theme switcher which allows user to toggle between a light and a dark theme. Switching between them also happens automatically based on user's system preferences. If a visitor has set the theme manually that selection is remembered in `localStorage`, and is restored on next visit. All handled by [use-dark-mode](https://github.com/donavon/use-dark-mode) Includes a theme switcher which allows user to toggle between a light and a dark theme. Switching between them also happens automatically based on user's system preferences.
If you want to know how, have a look at the respective components: If you want to know how, have a look at the respective components:
- [`src/components/molecules/ThemeSwitch.jsx`](src/components/molecules/ThemeSwitch.jsx) - [`src/components/molecules/ThemeSwitch.jsx`](src/components/molecules/ThemeSwitch.jsx)
- [`src/hooks/useDarkMode.js`](src/hooks/useDarkMode.js)
### 🏆 SEO component ### 🏆 SEO component

View File

@ -73,14 +73,6 @@ module.exports = {
theme_color_in_head: false // dynamically set in ThemeSwitch theme_color_in_head: false // dynamically set in ThemeSwitch
} }
}, },
{
resolve: 'gatsby-plugin-use-dark-mode',
options: {
classNameDark: 'dark',
classNameLight: 'light',
minify: true
}
},
'gatsby-plugin-react-helmet', 'gatsby-plugin-react-helmet',
'gatsby-plugin-sitemap', 'gatsby-plugin-sitemap',
'gatsby-plugin-offline', 'gatsby-plugin-offline',

28194
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,6 @@
"gatsby-plugin-sharp": "^3.0.1", "gatsby-plugin-sharp": "^3.0.1",
"gatsby-plugin-sitemap": "^3.0.0", "gatsby-plugin-sitemap": "^3.0.0",
"gatsby-plugin-svgr": "^3.0.0-beta.0", "gatsby-plugin-svgr": "^3.0.0-beta.0",
"gatsby-plugin-use-dark-mode": "^1.3.0",
"gatsby-plugin-webpack-size": "^2.0.1", "gatsby-plugin-webpack-size": "^2.0.1",
"gatsby-source-filesystem": "^3.0.0", "gatsby-source-filesystem": "^3.0.0",
"gatsby-transformer-json": "^3.0.0", "gatsby-transformer-json": "^3.0.0",
@ -51,7 +50,6 @@
"remark-parse": "^9.0.0", "remark-parse": "^9.0.0",
"remark-react": "^8.0.0", "remark-react": "^8.0.0",
"shortid": "^2.2.16", "shortid": "^2.2.16",
"use-dark-mode": "^2.3.1",
"vcf": "^2.1.0" "vcf": "^2.1.0"
}, },
"devDependencies": { "devDependencies": {

View File

@ -4,7 +4,7 @@ import posed, { PoseGroup } from 'react-pose'
import { fadeIn } from './atoms/Transitions' import { fadeIn } from './atoms/Transitions'
import Typekit from './atoms/Typekit' import Typekit from './atoms/Typekit'
import HostnameCheck from './atoms/HostnameCheck' import HostnameCheck from './atoms/HostnameCheck'
// import ThemeSwitch from './molecules/ThemeSwitch' import ThemeSwitch from './molecules/ThemeSwitch'
import Header from './organisms/Header' import Header from './organisms/Header'
import Footer from './organisms/Footer' import Footer from './organisms/Footer'
import { screen } from './Layout.module.css' import { screen } from './Layout.module.css'
@ -40,7 +40,7 @@ export default function Layout({ children, location }) {
<> <>
<Typekit /> <Typekit />
<HostnameCheck allowedHosts={allowedHosts} /> <HostnameCheck allowedHosts={allowedHosts} />
{/* <ThemeSwitch /> */} <ThemeSwitch />
<PoseGroup animateOnMount={process.env.NODE_ENV !== 'test'}> <PoseGroup animateOnMount={process.env.NODE_ENV !== 'test'}>
<RoutesContainer <RoutesContainer

View File

@ -1,7 +1,6 @@
import React, { memo, useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { Helmet } from 'react-helmet' import { Helmet } from 'react-helmet'
import useDarkMode from 'use-dark-mode'
import Icon from '../atoms/Icon' import Icon from '../atoms/Icon'
import { import {
checkboxContainer, checkboxContainer,
@ -10,16 +9,15 @@ import {
checkbox, checkbox,
label label
} from './ThemeSwitch.module.css' } from './ThemeSwitch.module.css'
import useDarkMode from '../../hooks/useDarkMode'
const ThemeToggle = memo(({ dark }) => ( const ThemeToggle = ({ dark }) => (
<span id="toggle" className={checkboxContainer} aria-live="assertive"> <span id="toggle" className={checkboxContainer} aria-live="assertive">
<Icon name="Sun" className={!dark ? null : 'active'} /> <Icon name="Sun" className={!dark ? null : 'active'} />
<span className={checkboxFake} /> <span className={checkboxFake} />
<Icon name="Moon" className={dark ? 'active' : null} /> <Icon name="Moon" className={dark ? 'active' : null} />
</span> </span>
)) )
ThemeToggle.displayName = 'ThemeToggle'
ThemeToggle.propTypes = { ThemeToggle.propTypes = {
dark: PropTypes.bool.isRequired dark: PropTypes.bool.isRequired
@ -27,7 +25,7 @@ ThemeToggle.propTypes = {
const ThemeToggleInput = ({ dark, toggleDark }) => ( const ThemeToggleInput = ({ dark, toggleDark }) => (
<input <input
onChange={() => toggleDark()} onChange={() => toggleDark(!dark)}
type="checkbox" type="checkbox"
name="toggle" name="toggle"
value="toggle" value="toggle"
@ -36,8 +34,6 @@ const ThemeToggleInput = ({ dark, toggleDark }) => (
/> />
) )
ThemeToggleInput.displayName = 'ThemeToggleInput'
ThemeToggleInput.propTypes = { ThemeToggleInput.propTypes = {
dark: PropTypes.bool.isRequired, dark: PropTypes.bool.isRequired,
toggleDark: PropTypes.func.isRequired toggleDark: PropTypes.func.isRequired
@ -60,10 +56,7 @@ HeadItems.propTypes = {
} }
export default function ThemeSwitch() { export default function ThemeSwitch() {
const { value, toggle } = useDarkMode(false, { const { value, toggle } = useDarkMode()
classNameDark: 'dark',
classNameLight: 'light'
})
const [themeColor, setThemeColor] = useState('') const [themeColor, setThemeColor] = useState('')
const [bodyClass, setBodyClass] = useState('') const [bodyClass, setBodyClass] = useState('')

60
src/hooks/useDarkMode.js Normal file
View File

@ -0,0 +1,60 @@
//
// adapted from
// https://github.com/daveschumaker/react-dark-mode-hook/blob/master/useDarkMode.js
//
import { useState, useEffect, useCallback } from 'react'
const isClient = typeof window === 'object'
function getDarkMode() {
// if (localStorage.getItem('theme') === 'dark') {
// return true
// } else if (localStorage.getItem('theme') === 'light') {
// return false
// }
if (
isClient &&
window.matchMedia &&
window.matchMedia('(prefers-color-scheme: dark)').matches
) {
return true
} else {
return false
}
}
export default function useDarkMode() {
const [darkMode, setDarkMode] = useState(getDarkMode)
//
// Handle system theme change events
//
const handleChange = useCallback(() => {
setDarkMode(getDarkMode())
}, [])
useEffect(() => {
if (!isClient) return false
const darkModeQuery = window.matchMedia('(prefers-color-scheme: dark)')
try {
// Handle Chrome & Firefox
darkModeQuery.addEventListener('change', handleChange)
} catch (addEventListenerError) {
try {
// Handle Safari
darkModeQuery.addListener('change', handleChange)
} catch (addListenerError) {
console.error(addListenerError)
}
}
return () =>
window
.matchMedia('(prefers-color-scheme: dark)')
.removeEventListener('change', handleChange)
}, [handleChange])
return { value: darkMode, toggle: setDarkMode }
}