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