Theme Switching with Styled Components
Sat May 27 2023 10:27:33 GMT+0000 (Coordinated Universal Time)
Saved by @Kristi
//Global.js includes our Global styles for the app
import { createGlobalStyle } from 'styled-components';
import * as theme from './Theme.styled';
const GlobalStyles = createGlobalStyle`
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: ${({ theme }) => theme.colors.background};
color: ${({ theme }) => theme.colors.text};
font-family: monospace;
overflow-x: hidden;
}
// theme buttons color - toggle button
.light {
background-color: ${theme.light.colors.header};
}
.dark {
background-color: ${theme.dark.colors.header};
}
// active theme - toggle button
.active{
border: 3px solid ${({ theme }) => theme.colors.border}; }
`;
export default GlobalStyles;
//Theme.styled.js which is included inside the Global.js, contains the themes colors
export const light = {
name: 'light-theme',
colors: {
header: 'hsl(0, 0%, 93%)',
background: 'hsl(0, 0%, 100%)',
footer: 'hsl(0, 1%, 38%)',
text: 'hsl(0, 1%, 16%)',
quoteBgc: 'hsl(60, 40%, 100%)',
quoteTitle: 'hsl(0, 1%, 38%)',
quoteBody: 'hsl(0, 1%, 38%);',
quoteBorder: 'hsl(0, 0%, 87%)',
border: 'hsl(0, 0%, 87%)',
},
};
export const dark = {
name: 'dark-theme',
colors: {
header: 'hsl(0, 0%, 20%)',
background: 'hsl(0, 1%, 16%)',
footer: 'hsl(0, 0%, 93%)',
text: 'hsl(0, 0%, 100%)',
quoteBgc: 'hsl(0, 0%, 35%)',
quoteTitle: 'hsl(0, 0%, 100%)',
quoteBody: 'hsl(0, 0%, 100%)',
quoteBorder: 'hsl(0, 0%, 59%)',
border: 'hsl(0, 0%, 78%)',
},
};
//App.js
import { ThemeProvider } from 'styled-components';
import { light, dark, blue, green, brown, pink } from './styles/Theme.styled';
import { useState, useEffect } from 'react';
function App() {
const [selectedTheme, setSelectedTheme] = useState(light);
// function to handle user theme selection on click and save it to local storage
const HandleThemeChange = (theme) => {
setSelectedTheme(theme);
localStorage.setItem('current-theme', JSON.stringify(theme));
};
// react hook to get the theme selected by the user that is saved in local storage
useEffect(() => {
const currentTheme = JSON.parse(localStorage.getItem('current-theme'));
if (currentTheme) {
setSelectedTheme(currentTheme);
}
}, []);
return (
<ThemeProvider theme={selectedTheme}>
<div className="App">
<GlobalStyles />
<ThemeContainer>
<span>Themes: </span>
<ThemeButton
className={`light ${selectedTheme === light ? 'active' : ''}`}
onClick={() => HandleThemeChange(light)}
></ThemeButton>
<ThemeButton
className={`dark ${selectedTheme === dark ? 'active' : ''}`}
onClick={() => HandleThemeChange(dark)}
></ThemeButton>
</ThemeContainer>
</div>
</ThemeProvider>
);
}
export default App;
//The components that you use inside the ThemeProvider, in order to make the colors dynamic :
export const ThemeContainer = styled.div`
background-color: ${({ theme }) => theme.colors.background};
border-bottom: 1px solid ${({ theme }) => theme.colors.border};
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
padding: 10px;
`;
export const ThemeButton = styled.button`
border: 1px solid ${({ theme }) => theme.colors.border};
margin: 0 5px;
padding: 10px;
font-size: 0.5rem;
border-radius: 5px;
width: 20px;
height: 20px;
cursor: pointer;
&:hover {
box-shadow: 2px 2px 2px ${({ theme }) => theme.colors.border};
}
`;
//To use the theme object in another component and apply it to an SVG's inline style:
import { useTheme } from 'styled-components';
const Navigation = () => {
const theme = useTheme();
return (
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="16">
<g style={{ fill: theme.colors.primary }} fillRule="evenodd">
<path d="M0 0h19.692v3.692H0zM0 6.154h19.692v3.692H0zM0 12.308h19.692V16H0z" />
</g>
</svg>
)
};
export default Navigation;
Github repository for the code: https://github.com/Timonwa/theme-switching
https://blog.logrocket.com/build-react-theme-switcher-app-styled-components/


Comments