DEV Community

Cover image for Fast Track to Dark Mode with Styled Components and React
Agney Menon
Agney Menon

Posted on • Originally published at blog.agney.dev

Fast Track to Dark Mode with Styled Components and React

This post describes a fast track to dark mode with Styled Components and a couple of other packages which is currently implemented on this blog.

Note that we will not be discussing the implications or concept behind dark mode, there are enough articles on the web that do that already. Let's get straight to business.

We will start with a ReactJS hook for dark mode. We will also add in the gatsby plugin that helps prevent flashing on load for the same hook.

npm i use-dark-mode gatsby-plugin-use-dark-mode

Now, we need a button to change the mode, we could add any button but let's get the pre-made beautiful SVG button:

npm i react-dark-mode-toggle

Let's split our theme to colors and others:

const darkColors = {
  background: `#121212`,
  textColor: `rgba(255, 255, 255, 0.85)`,
}
const lightColors = {
  background: `#FFFFFF`,
  textColor: `rgba(0, 0, 0, 0.8)`,
}
const theme = {
  other: {},
}
export default getTheme(mode) {
  return {
    ...theme,
    colors: mode === 'light' ? lightColors : darkColors,
  }
}

Guide to using ThemeProvider in docs

Now, let's wire the button and the hook together:

import useDarkMode from 'use-dark-mode';
import DarkModeToggle from 'react-dark-mode-toggle';

import getTheme from './theme';

function Layout({ children }) {
  const darkMode = useDarkMode(false);
  const theme = getTheme(darkMode.value ? 'dark' : 'light');
  return (
    <>
      <header>
        <DarkModeToggle
          onChange={darkMode.toggle}
          checked={darkMode.value}
          size={50}
        />
      </header>
      {children}
    </>
  );
}

export default App;

and that's it! We have dark mode. You might have to adjust some other variables for hover styles and others, but this is a great start.

Bonus: Global Styles:

import { createGlobalStyle } from 'styled-components';

const GlobalStyles = createGlobalStyle`
  body {
    color: ${props => props.theme.colors.textColor};
    background-color: ${props => props.theme.colors.background};
  }
  body.dark-mode {
    img:not([src*=".svg"]) {
      filter: grayscale(50%);
    }
  }
`;

export default GlobalStyles;

Crossposted from my blog.
Subscribe to my monthly On the Web newsletter

Top comments (0)