Theme Switching with Styled Components

PHOTO EMBED

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;
content_copyCOPY

Github repository for the code: https://github.com/Timonwa/theme-switching

https://blog.logrocket.com/build-react-theme-switcher-app-styled-components/