README.md

February 20, 2026 ยท View on GitHub

React Toggle Dark Mode

Version License: MIT PRs Welcome Bundle size

๐ŸŒƒ Animated dark mode toggle as seen in blogs!

Supports React 16.14+ through 19.

Interactive sun and moon transition

Prerequisites

  • node >=20

Installation

npm i react-toggle-dark-mode

or with pnpm:

pnpm add react-toggle-dark-mode

Usage

import * as React from 'react';
import { createRoot } from 'react-dom/client';
import { DarkModeSwitch } from 'react-toggle-dark-mode';

const App = () => {
  const [isDarkMode, setDarkMode] = React.useState(false);

  const toggleDarkMode = (checked: boolean) => {
    setDarkMode(checked);
  };

  return (
    <DarkModeSwitch
      style={{ marginBottom: '2rem' }}
      checked={isDarkMode}
      onChange={toggleDarkMode}
      size={120}
    />
  );
};

const rootElement = document.getElementById('root');

if (!rootElement) {
  throw new Error('Unable to find root element');
}

createRoot(rootElement).render(<App />);

API

DarkModeSwitch

Props

NameTypeDefault ValueDescription
onChange(checked: boolean) => voidEvent that triggers when icon is clicked.
checkedbooleanfalseCurrent icon state.
styleReact.CSSPropertiesCSS properties object applied to the button wrapper.
sizenumber | string24SVG size.
animationPropertiesPartial animation properties objectdefaultProperties (see below)Override only the fields you want; missing fields are merged with defaults.
moonColorstringwhiteColor of the moon.
sunColorstringblackColor of the sun.
aria-labelstringToggle dark modeAccessible label for the control. Ignored when aria-labelledby is provided.
aria-labelledbystringLinks the control to an external label element.
onClick(event: React.MouseEvent)=>voidOptional button click handler. Call event.preventDefault() to prevent toggling on click.

All valid button attributes (except children) are forwarded to the underlying button element.

Default Animation Properties

const defaultProperties = {
  dark: {
    circle: {
      r: 9,
    },
    mask: {
      cx: '50%',
      cy: '23%',
    },
    svg: {
      transform: 'rotate(40deg)',
    },
    lines: {
      opacity: 0,
    },
  },
  light: {
    circle: {
      r: 5,
    },
    mask: {
      cx: '100%',
      cy: '0%',
    },
    svg: {
      transform: 'rotate(90deg)',
    },
    lines: {
      opacity: 1,
    },
  },
  springConfig: { mass: 4, tension: 250, friction: 35 },
};

Contributors

Thanks goes to these wonderful people (emoji key):


Jose Felix

๐Ÿ’ป ๐Ÿ“– โš ๏ธ

This project follows the all-contributors specification. Contributions of any kind are welcome!

Show your support

Give a โญ๏ธ if this project helped you!