<div id="app"></div>
const { createGlobalStyle, ThemeProvider } = styled;
const { useState, useEffect } = React;
const GlobalStyles = createGlobalStyle`
*,
*::after,
*::before {
box-sizing: border-box;
}
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
background: ${({ theme }) => theme.body};
color: ${({ theme }) => theme.text};
padding: 0;
margin: 0;
font-family: BlinkMacSystemFont, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
transition: all 0.25s linear;
}
footer {
position: absolute;
bottom: 5%;
left: 50%;
transform: translateX(-50%);
}
small {
display: block;
}
button {
display: block;
}
a {
color: ${({ theme }) => theme.text};
}
`;
const lightTheme = {
body: '#e2e2e2',
text: '#363537',
toggleBorder: '#fff',
gradient: 'linear-gradient(#39598A, #79D7ED)',
}
const darkTheme = {
body: '#363537',
text: '#FAFAFA',
toggleBorder: '#6B8096',
gradient: 'linear-gradient(#091236, #1E215D)',
}
const Toggle = ({ theme, toggleTheme }) => {
const isLight = theme === 'light';
return (
<ToggleContainer lightTheme={isLight} onClick={toggleTheme}>
<img src="https://image.flaticon.com/icons/svg/1164/1164954.svg" width="224" height="224" alt="Sun free icon" title="Sun free icon"/>
<img src="https://image.flaticon.com/icons/svg/2033/2033921.svg" width="224" height="224" alt="Moon free icon" title="Moon free icon"/>
</ToggleContainer>
);
};
const ToggleContainer = styled.button`
position: relative;
display: flex;
justify-content: space-between;
background: ${({ theme }) => theme.gradient};
width: 8rem;
height: 3.5rem;
margin: 0 auto;
border-radius: 30px;
border: 2px solid ${({ theme }) => theme.toggleBorder};
font-size: 0.5rem;
padding: 0.5rem;
overflow: hidden;
cursor: pointer;
img {
max-width: 2.5rem;
height: auto;
transition: all 0.3s linear;
&:first-child {
transform: ${({ lightTheme }) => lightTheme ? 'translateY(0)' : 'translateY(100px)'};
}
&:nth-child(2) {
transform: ${({ lightTheme }) => lightTheme ? 'translateY(-100px)' : 'translateY(0)'};
}
}
`;
const useDarkMode = () => {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
if (theme === 'light') {
setTheme('dark')
window.localStorage.setItem('theme', 'dark');
} else {
setTheme('light')
window.localStorage.setItem('theme', 'light');
}
};
useEffect(() => {
const localTheme = window.localStorage.getItem('theme');
if (localTheme) {
setTheme(localTheme);
} else {
window.localStorage.setItem('theme', 'light');
}
})
return [theme, toggleTheme]
};
function App() {
const [theme, toggleTheme] = useDarkMode();
const themeMode = theme === 'light' ? lightTheme : darkTheme;
return (
<ThemeProvider theme={themeMode}>
<div>
<GlobalStyles />
<Toggle theme={theme} toggleTheme={toggleTheme} />
<h1>It's a {theme === 'light' ? 'light theme' : 'dark theme'}!</h1>
<footer>
<span>Credits:</span>
<small><b>Sun</b> icon made by <a href="https://www.flaticon.com/authors/smalllikeart">smalllikeart</a> from <a href="https://www.flaticon.com">www.flaticon.com</a></small>
<small><b>Moon</b> icon made by <a href="https://www.freepik.com/home">Freepik</a> from <a href="https://www.flaticon.com">www.flaticon.com</a></small>
</footer>
</div>
</ThemeProvider>
);
};
ReactDOM.render(<App />, document.getElementById('app'));
View Compiled
This Pen doesn't use any external CSS resources.