NashTech Blog

Table of Contents
Light-Dark

Looking to enhance your website’s accessibility and modernity by adding a dark mode feature? Follow this comprehensive guide on implementing dark mode in React, complete with best practices.

Step 1: Create React app using Vite (skip if already created)

Begin by setting up the React App using Vite, a popular build tool known for simplifying and expediting the development process. Use the following command to initiate the project:

yarn create vite

Vite will prompt you to specify a Project name, select a framework, and choose a variant. For this guide, choose “react” as the framework and “react-ts” as the variant. Once your app is set up, navigate to the project, install dependencies, and you’re ready to proceed.

Step 2: Create theme context

In the /src/contexts folder, open a theme-context.ts file and create the theme context.

// theme-context.ts
import { createContext } from 'react';
export const ThemeContext = createContext({
theme: '',
setTheme: (theme: string) => {},
});

This context will receive “light” or “dark” as input and return the same as output.

Step 3: Create theme-variables.scss file with variables for the light and dark themes

Within the src folder, create a styles folder and a theme-variables.scss file. This file will contain color alternatives for light and dark modes.

// theme-variables.scss
$themes: (
light: (
colorHeaderFooter: #fff,
colorText: #000,
colorBackground: #f8f8fa,
),
dark: (
colorHeaderFooter: #36394c,
colorText: #eff2f7,
colorBackground: #222736,
),
);

Continue by creating a mixin named themify to generate dark and light themes. Also, create a function called themed to retrieve the color value for the current theme.

// theme-variables.scss
@mixin themify($themes) {
@each $theme, $map in $themes {
.theme-#{$theme} & {
$theme-map: () !global;
@each $key, $submap in $map {
$value: map-get(map-get($themes, $theme), '#{$key}');
$theme-map: map-merge(
$theme-map,
(
$key: $value,
),
) !global;
}
@content;
$theme-map: null !global;
}}}
@function themed($key) {
@return map-get($theme-map, $key); }

Step 4: Wrap the App component in the theme context

In the App.tsx file, import the Theme context created in Step 2.

// App.tsx
import { ThemeContext } from './contexts/theme-context';

Create a state for the current theme, initially set to “light,” and wrap the entire component within the Theme provider.

// App.tsx
const [theme, setTheme] = useState('light');

<ThemeContext.Provider value={{ theme, setTheme }}>
  <div className={`theme-${theme}`}>
    <Layout>
      {/* Your code here */}
    </Layout>
  </div>
</ThemeContext.Provider>

This context provider will provide the current theme name, used in the className of the theme wrapper.

Step 5: Create a layout component with a light/dark mode toggle button

Create a simple toggle button to switch between themes in a new Header.tsx file.

// Header.tsx
import { FC, useContext } from 'react';
import { ThemeContext } from '../contexts/theme-context';
import logoIcon from '../images/logo-icon.png';
import './styles.scss';

const Header: FC = () => {
  const { theme, setTheme } = useContext(ThemeContext);

  const handleThemeChange = () => {
    const isCurrentDark = theme === 'dark';
    setTheme(isCurrentDark ? 'light' : 'dark');
  };

  return (
    <header className="header">
      {/* Header content */}
      <div className="toggle-btn-section">
        {/* Toggle button */}
        <div className={`toggle-checkbox m-vertical-auto`}>
          <input
            className="toggle-btn__input"
            type="checkbox"
            name="checkbox"
            onChange={handleThemeChange}
            checked={theme === 'light'}
          />
          <button type="button" className={`toggle-btn__input-label`} onClick={handleThemeChange}></button>
        </div>
      </div>
    </header>
  );
};

export default Header;

This toggle button changes the theme on click. The theme value is stored in localStorage for persistence.

Step 6: Detect the browser’s default mode if any to set up the default theme

In App.tsx, set the theme’s default value based on the browser’s default mode using matchMedia.

// App.tsx
const isBrowserDefaultDark = () => window.matchMedia('(prefers-color-scheme: dark)').matches;
const [theme, setTheme] = useState(isBrowserDefaultDark() ? 'dark' : 'light');

Step 7: Set the default theme in the localStorage

Save the theme in localStorage in the Header.tsx file, adding the following line to the handleThemeChange function.

// Header.tsx
localStorage.setItem('theme', isCurrentDark ? 'light' : 'dark');

Now, the default theme is retrieved from localStorage whenever a user enters the website.

With these steps, your dark mode in react app is ready for use.

If you liked this blog, please share it with your friends and colleagues. Connect with FE Competency on LinkedIn to read more about such topics.

Picture of Anuj

Anuj

As a skilled web developer, I specialize in React and Angular frameworks, proficiently utilizing various JavaScript libraries to create dynamic and seamless online experiences. My dedication to staying abreast of industry trends ensures that I deliver innovative solutions. With a focus on optimal user interfaces and functionality, I thrive in collaborative environments, bringing creativity and efficiency to web development projects. My expertise lies in crafting engaging digital solutions that align with the evolving landscape of web technologies. Let's embark on a journey of creating remarkable and user-centric online platforms.

Leave a Comment

Your email address will not be published. Required fields are marked *

Suggested Article

Scroll to Top