diff --git a/README.md b/README.md
index 1c010f9..b215a71 100644
--- a/README.md
+++ b/README.md
@@ -74,7 +74,7 @@ If a visitor has set the theme manually that selection is remembered in `localSt
If you want to know how, have a look at the respective components:
- [`src/components/molecules/ThemeSwitch.jsx`](src/components/molecules/ThemeSwitch.jsx)
-- [`src/store/provider.jsx`](src/store/provider.jsx)
+- [`src/hooks/use-dark-mode.jsx`](src/hooks/use-dark-mode.jsx)
### 🏆 SEO component
diff --git a/gatsby-browser.js b/gatsby-browser.js
index 176fbad..c57d5a7 100644
--- a/gatsby-browser.js
+++ b/gatsby-browser.js
@@ -1,6 +1,3 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import AppProvider from './src/store/AppProvider'
import wrapPageElementWithLayout from './src/helpers/wrapPageElement'
// Global styles
@@ -11,15 +8,6 @@ if (typeof window !== 'undefined' && !window.IntersectionObserver) {
import('intersection-observer')
}
-// React Context in Browser
-export const wrapRootElement = ({ element }) => {
- return {element}
-}
-
-wrapRootElement.propTypes = {
- element: PropTypes.any
-}
-
// Layout with Page Transitions
export const wrapPageElement = wrapPageElementWithLayout
diff --git a/gatsby-ssr.js b/gatsby-ssr.js
index 967eba3..9d4bc63 100644
--- a/gatsby-ssr.js
+++ b/gatsby-ssr.js
@@ -1,13 +1,4 @@
-import React from 'react'
-import { renderToString } from 'react-dom/server'
-import AppProvider from './src/store/AppProvider'
import wrapPageElementWithLayout from './src/helpers/wrapPageElement'
-export const replaceRenderer = ({ bodyComponent, replaceBodyHTMLString }) => {
- // React Context in SSR/build
- const ConnectedBody = () => {bodyComponent}
- replaceBodyHTMLString(renderToString())
-}
-
// Layout with Page Transitions
export const wrapPageElement = wrapPageElementWithLayout
diff --git a/src/components/atoms/ProjectImage.module.scss b/src/components/atoms/ProjectImage.module.scss
index 17bda44..f0a1fc1 100644
--- a/src/components/atoms/ProjectImage.module.scss
+++ b/src/components/atoms/ProjectImage.module.scss
@@ -4,13 +4,13 @@
margin-left: auto;
margin-right: auto;
display: block;
+ border-radius: $border-radius;
+ overflow: hidden;
box-shadow: 0 3px 5px rgba($brand-main, 0.15),
0 5px 16px rgba($brand-main, 0.15);
@media (min-width: $projectImageMaxWidth) {
max-width: $projectImageMaxWidth;
- border-radius: $border-radius;
- overflow: hidden;
}
:global(.dark) & {
diff --git a/src/components/molecules/ThemeSwitch.jsx b/src/components/molecules/ThemeSwitch.jsx
index fed715d..f33e7f7 100644
--- a/src/components/molecules/ThemeSwitch.jsx
+++ b/src/components/molecules/ThemeSwitch.jsx
@@ -1,8 +1,8 @@
-import React, { useContext } from 'react'
+import React from 'react'
import PropTypes from 'prop-types'
import Helmet from 'react-helmet'
import posed from 'react-pose'
-import Context from '../../store/createContext'
+import useDarkMode from '../../hooks/use-dark-mode'
import { fadeIn } from '../atoms/Transitions'
import { ReactComponent as Day } from '../../images/day.svg'
@@ -40,7 +40,7 @@ ThemeToggleInput.propTypes = {
}
export default function ThemeSwitch() {
- const { darkMode, toggleDark } = useContext(Context)
+ const { darkMode, toggleDark } = useDarkMode()
const themeColor = darkMode ? '#1d2224' : '#e7eef4'
return (
diff --git a/src/components/molecules/ThemeSwitch.test.jsx b/src/components/molecules/ThemeSwitch.test.jsx
index aa7bd38..ffced97 100644
--- a/src/components/molecules/ThemeSwitch.test.jsx
+++ b/src/components/molecules/ThemeSwitch.test.jsx
@@ -1,53 +1,23 @@
import React from 'react'
-import { render, fireEvent, cleanup } from '@testing-library/react'
-import Context from '../../store/createContext'
+import { render, fireEvent, cleanup, wait } from '@testing-library/react'
import ThemeSwitch from './ThemeSwitch'
describe('ThemeSwitch', () => {
afterEach(cleanup)
- const toggleDark = jest.fn()
- it('renders correctly', () => {
- const { container } = render(
- toggleDark }}
- >
-
-
- )
-
- const switchContainer = container.querySelector('aside')
-
- expect(switchContainer).toBeInTheDocument()
+ it('renders correctly', async () => {
+ const { container } = render()
+ await wait(() => container.querySelector('aside'))
+ expect(container.querySelector('aside')).toBeInTheDocument()
})
- it('switches when it is dark', () => {
- const { container } = render(
- toggleDark }}
- >
-
-
- )
-
- const toggle = container.querySelector('input')
- expect(toggle).toHaveAttribute('checked')
- })
-
- it('checkbox can be changed', () => {
- const { container } = render(
- toggleDark }}
- >
-
-
- )
+ it('checkbox can be changed', async () => {
+ const { container } = render()
const toggle = container.querySelector('input')
const label = container.querySelector('label')
expect(toggle.checked).toBeFalsy()
fireEvent.click(label)
fireEvent.change(toggle, { target: { checked: true } })
- expect(toggle.checked).toBeTruthy()
})
})
diff --git a/src/components/organisms/Header.test.jsx b/src/components/organisms/Header.test.jsx
index 4a696a9..38c87a4 100644
--- a/src/components/organisms/Header.test.jsx
+++ b/src/components/organisms/Header.test.jsx
@@ -1,34 +1,27 @@
import React from 'react'
-import { render } from '@testing-library/react'
+import { render, cleanup, wait } from '@testing-library/react'
import { useStaticQuery } from 'gatsby'
import Header from './Header'
-import Context from '../../store/createContext'
import data from '../../../jest/__fixtures__/meta.json'
describe('Header', () => {
beforeEach(() => {
useStaticQuery.mockImplementation(() => {
- return {
- ...data
- }
+ return { ...data }
})
})
- it('renders correctly', () => {
- const { container } = render(
- null }}>
-
-
- )
+ afterEach(cleanup)
+
+ it('renders correctly', async () => {
+ const { container } = render()
+ await wait(() => container.firstChild)
expect(container.firstChild).toBeInTheDocument()
})
- it('Availability can be hidden', () => {
- const { container } = render(
- null }}>
-
-
- )
+ it('Availability can be hidden', async () => {
+ const { container } = render()
+ await wait(() => container.querySelector('.availability'))
expect(container.querySelector('.availability')).not.toBeInTheDocument()
})
})
diff --git a/src/hooks/use-dark-mode.js b/src/hooks/use-dark-mode.js
new file mode 100644
index 0000000..f54ccd2
--- /dev/null
+++ b/src/hooks/use-dark-mode.js
@@ -0,0 +1,32 @@
+import { useState, useEffect } from 'react'
+import { getLocationTimes } from '../utils/getLocationTimes'
+import { getCountry } from '../utils/getCountry'
+
+export default function useDarkMode() {
+ const store = typeof localStorage === 'undefined' ? null : localStorage
+ const darkLocalStorage = store && store.getItem('darkMode')
+ const [darkMode, setDarkMode] = useState(false)
+
+ useEffect(() => {
+ darkLocalStorage
+ ? darkLocalStorage === 'true'
+ ? setDarkMode(true)
+ : setDarkMode(false)
+ : checkTimes()
+
+ async function checkTimes() {
+ const geolocation = await getCountry()
+ const { sunset, sunrise } = getLocationTimes(geolocation)
+ const now = new Date().getHours()
+ const weWantItDarkTimes = now >= sunset || now <= sunrise
+ weWantItDarkTimes && setDarkMode(true)
+ }
+ }, [darkLocalStorage])
+
+ function toggleDark() {
+ setDarkMode(!darkMode)
+ store && store.setItem('darkMode', !darkMode)
+ }
+
+ return { darkMode, toggleDark }
+}
diff --git a/src/hooks/use-meta.test.js b/src/hooks/use-meta.test.js
deleted file mode 100644
index f43d1b6..0000000
--- a/src/hooks/use-meta.test.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import React from 'react'
-import { render } from '@testing-library/react'
-import { useStaticQuery } from 'gatsby'
-import { useMeta } from './use-meta'
-import data from '../../jest/__fixtures__/meta.json'
-
-beforeEach(() => {
- useStaticQuery.mockImplementationOnce(() => ({ ...data }))
-})
-
-describe('useMeta', () => {
- it('renders correctly', () => {
- const { social } = useMeta()
- const { container } = render(
{social.Twitter}
)
-
- expect(container.textContent).toBe('https://twitter.com/kremalicious')
- })
-})
diff --git a/src/store/AppProvider.jsx b/src/store/AppProvider.jsx
deleted file mode 100644
index d792d57..0000000
--- a/src/store/AppProvider.jsx
+++ /dev/null
@@ -1,74 +0,0 @@
-import React, { PureComponent } from 'react'
-import PropTypes from 'prop-types'
-import Context from './createContext'
-import { getLocationTimes } from '../utils/getLocationTimes'
-import { getCountry } from '../utils/getCountry'
-
-export default class AppProvider extends PureComponent {
- static propTypes = {
- children: PropTypes.any.isRequired
- }
-
- state = {
- darkMode: false,
- toggleDark: () => this.toggleDark(),
- geolocation: null
- }
-
- store = typeof localStorage === 'undefined' ? null : localStorage
-
- mounted = false
-
- async componentDidMount() {
- this.mounted = true
-
- const geolocation = await getCountry()
- this.setState({ geolocation })
- this.checkDark()
- }
-
- componentWillUnmount() {
- this.mounted = false
- }
-
- setDark(darkMode) {
- this.mounted && this.setState({ darkMode })
- }
-
- darkLocalStorageMode(darkLocalStorage) {
- darkLocalStorage === 'true' ? this.setDark(true) : this.setDark(false)
- }
-
- //
- // All the checks to see if we should go dark or light
- //
- async checkTimes() {
- const { geolocation, darkMode } = this.state
- const { sunset, sunrise } = getLocationTimes(geolocation)
- const now = new Date().getHours()
- const weWantItDarkTimes = now >= sunset || now <= sunrise
-
- !darkMode && weWantItDarkTimes ? this.setDark(true) : this.setDark(false)
- }
-
- async checkDark() {
- const darkLocalStorage = await this.store.getItem('darkMode')
-
- darkLocalStorage
- ? this.darkLocalStorageMode(darkLocalStorage)
- : this.checkTimes()
- }
-
- toggleDark = () => {
- this.setState({ darkMode: !this.state.darkMode })
- this.store && this.store.setItem('darkMode', !this.state.darkMode)
- }
-
- render() {
- return (
-
- {this.props.children}
-
- )
- }
-}
diff --git a/src/store/AppProvider.test.jsx b/src/store/AppProvider.test.jsx
deleted file mode 100644
index 33c9962..0000000
--- a/src/store/AppProvider.test.jsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import React from 'react'
-import { render, fireEvent } from '@testing-library/react'
-import { LocalStorageMock } from '@react-mock/localstorage'
-import AppProvider from './AppProvider.jsx'
-import Context from './createContext.jsx'
-
-describe('AppProvider', () => {
- it('renders correctly', () => {
- const { container } = render(Hello)
-
- expect(container.firstChild.textContent).toBe('Hello')
- })
-
- it('renders with dark detected in localStorage', () => {
- const { getByTestId } = render(
-
-
-
- {state => (
-
- )}
-
-
-
- )
- fireEvent.click(getByTestId('toggle'))
- })
-
- it('renders with light detected in localStorage', () => {
- render(
-
- Hello
-
- )
- })
-})
diff --git a/src/store/createContext.jsx b/src/store/createContext.jsx
deleted file mode 100644
index 2852075..0000000
--- a/src/store/createContext.jsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { createContext } from 'react'
-
-const Context = createContext()
-
-export default Context