Blog>
Snippets

Implementing a Dark Mode Toggle with Next.js and styled-components

Use styled-components to create a toggle that switches between light and dark modes in a Next.js app.
import { ThemeProvider, createGlobalStyle } from 'styled-components';
import { useState, useEffect } from 'react';

// Define our theme objects for light and dark modes
const lightTheme = {
  body: '#FFF',
  text: '#363537'
};

const darkTheme = {
  body: '#363537',
  text: '#FAFAFA'
};

// Create a global style that will be altered based on the current theme
const GlobalStyle = createGlobalStyle`
  body {
    background-color: ${props => props.theme.body};
    color: ${props => props.theme.text};
    transition: all 0.25s linear;
  }
`;

function MyApp({ Component, pageProps }) {
  // State to hold the current theme
  const [theme, setTheme] = useState('light');

  // Function to toggle the theme state
  const toggleTheme = () => {
    theme === 'light' ? setTheme('dark') : setTheme('light');
  };

  // Use useEffect to set the theme based on user preference on mount
  useEffect(() => {
    const localTheme = window.localStorage.getItem('theme');
    localTheme && setTheme(localTheme);
  }, []);

  // Save the user's theme preference
  useEffect(() => {
    window.localStorage.setItem('theme', theme);
  }, [theme]);

  return (
    <ThemeProvider theme={theme === 'light' ? lightTheme : darkTheme}>
      <GlobalStyle />
      <button onClick={toggleTheme}>Toggle Theme</button>
      <Component {...pageProps} />
    </ThemeProvider>
  );
}

export default MyApp;
This code creates a Next.js app with a ThemeProvider from styled-components to manage the light and dark themes. The GlobalStyle component adjusts the look of the page based on the theme. The MyApp component maintains the theme state, provides a toggleTheme function to change it, and uses the local storage to remember the user's preference.