Search code examples
reactjsstyled-components

How to toggle css style using styled-components?


I have created a toggle switch that changes from dark mode to light mode. I am trying to add style which will change the fill: "" of the svg when I click toggle. path:first-child is upper icon, path:last-child is bottom icon.

icon

import { ReactComponent as ModeIcon} from '../../../assets/icons/mode-icon.svg';
import styled from 'styled-components';
import ThemeContext from "../../../store/themeContext";
import { useContext } from "react";

const Switcher = () => {
  const themeCtx = useContext(ThemeContext);
  const ToggleMode = () => {
    themeCtx.toggleMode()
  }
  return (
    <StyledSwitcher><ModeIcon onClick={ToggleMode}/></StyledSwitcher>
  )
}

export default Switcher;

const StyledSwitcher = styled.div`
svg{

  path:first-child{
    fill: #005FCE;
  }
  path:last-child{
    fill: #white;
  }
}
`;
import React, {useState} from 'react'
import { string } from 'yup';

type ContextObj = {
    toggleMode: any;
    theme: string;
  };

const ThemeContext = React.createContext<ContextObj>({
  toggleMode: () => {},
  theme: "dark",
  });

export const ThemeContextProvider = (props: any) => {
    const [theme, setTheme] = useState("dark");
  
    const themeToggler = ()=> {
      theme ==='light' ? setTheme('dark') : setTheme('light');
      console.log("Swiutch toggle")
    }

      const contextValue: ContextObj = {
        toggleMode: themeToggler,
        theme: theme,
  };
  return (
    <ThemeContext.Provider value={contextValue}>{props.children}</ThemeContext.Provider>
  )
};
export default ThemeContext

Solution

  • For first, you should provide 'theme' value from context to you component (like you did with toggleMode()). Then you can add 'theme' class attribute to your StyledSwitcher, for example:

    const Switcher = () => {
      const themeCtx = useContext(ThemeContext);
      const ToggleMode = () => {
        themeCtx.toggleMode()
      }
    
      const themeValue = () => {
        themeCtx.theme()
      }
      return (
        <StyledSwitcher className={themeValue}><ModeIcon onClick={ToggleMode}/></StyledSwitcher>
      )
    }
    

    After that, configure you styled component to work with that additional class:

    const StyledSwitcher = styled.div`
      &.light{
        svg{
          path:first-child{ fill: #005FCE; }
          path:last-child{ fill: #white; }
        }
      }
      &.dark{
        svg{
          path:first-child{ fill: #white; }
          path:last-child{ fill: #005FCE; }
        }
      }
    `;