MCPcopy Index your code
hub / github.com/GoogleChromeLabs/dark-mode-toggle

github.com/GoogleChromeLabs/dark-mode-toggle @v0.18.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.18.0 ↗ · + Follow
23 symbols 42 edges 6 files 0 documented · 0%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

<dark-mode-toggle> Element

Published on webcomponents.org

A custom element that allows you to easily put a Dark Mode 🌒 toggle or switch on your site, so you can initially adhere to your users' preferences according to prefers-color-scheme, but also allow them to (optionally permanently) override their system setting for just your site.

📚 Read all(!) about dark mode in the related article Hello Darkness, My Old Friend.

Installation

Install from npm:

npm install --save dark-mode-toggle

Or, alternatively, use a <script type="module"> tag (served from unpkg's CDN):

<script type="module" src="https://unpkg.com/dark-mode-toggle"></script>

Dark mode toggle live coding sample.

(See the original HD version so you can pause.)

Usage

There are three ways how you can use <dark-mode-toggle>:

① Using different stylesheets per color scheme that are conditionally loaded

The custom element assumes that you have organized your CSS in different files that you load conditionally based on the media attribute in the stylesheet's corresponding link element. This is a great performance pattern, as you don't force people to download CSS that they don't need based on their current theme preference, yet non-matching stylesheets still get loaded, but don't compete for bandwidth in the critical rendering path. You can also have more than one file per theme. The example below illustrates the principle.

<head>
  <link rel="stylesheet" href="https://github.com/GoogleChromeLabs/dark-mode-toggle/raw/v0.18.0/common.css" />
  <link
    rel="stylesheet"
    href="https://github.com/GoogleChromeLabs/dark-mode-toggle/raw/v0.18.0/light.css"
    media="(prefers-color-scheme: light)"
  />
  <link rel="stylesheet" href="https://github.com/GoogleChromeLabs/dark-mode-toggle/raw/v0.18.0/dark.css" media="(prefers-color-scheme: dark)" />
  <script
    type="module"
    src="https://googlechromelabs.github.io/dark-mode-toggle/src/dark-mode-toggle.mjs"
  ></script>
</head>

<main>
  <h1>Hi there</h1>
  <img
    src="https://googlechromelabs.github.io/dark-mode-toggle/demo/cat.jpg"
    alt="Sitting cat in front of a tree"
    width="320"
    height="195"
  />


Check out the dark mode toggle in the upper right corner!


</main>
<aside>
  <dark-mode-toggle
    id="dark-mode-toggle-1"
    legend="Theme Switcher"
    appearance="switch"
    dark="Dark"
    light="Light"
    remember="Remember this"
  ></dark-mode-toggle>
</aside>

The above method might cause flashing (#77) when the page loads, as the dark mode toggle module is loaded after the page is rendered. A loader script can be used to apply the saved theme before the page is rendered. Wrap the stylesheet tags with <noscript id="dark-mode-toggle-stylesheets">...</noscript> and add the loader script as follows:

<head>
  <link rel="stylesheet" href="https://github.com/GoogleChromeLabs/dark-mode-toggle/raw/v0.18.0/common.css" />
  <noscript id="dark-mode-toggle-stylesheets">
    <link
      rel="stylesheet"
      href="https://github.com/GoogleChromeLabs/dark-mode-toggle/raw/v0.18.0/light.css"
      media="(prefers-color-scheme: light)"
    />
    <link
      rel="stylesheet"
      href="https://github.com/GoogleChromeLabs/dark-mode-toggle/raw/v0.18.0/dark.css"
      media="(prefers-color-scheme: dark)"
    />
    <meta name="color-scheme" content="dark light" />
  </noscript>
  <script src="https://googlechromelabs.github.io/dark-mode-toggle/src/dark-mode-toggle-stylesheets-loader.js"></script>
  <script
    type="module"
    src="https://googlechromelabs.github.io/dark-mode-toggle/src/dark-mode-toggle.mjs"
  ></script>
</head>

② Using a CSS class that you toggle

If you prefer to not split your CSS in different files based on the color scheme, you can instead work with a class that you toggle, for example class="dark". You can see this in action in this demo.

import * as DarkModeToggle from 'https://googlechromelabs.github.io/dark-mode-toggle/src/dark-mode-toggle.mjs';

const toggle = document.querySelector('dark-mode-toggle');
const body = document.body;

// Set or remove the `dark` class the first time.
toggle.mode === 'dark'
  ? body.classList.add('dark')
  : body.classList.remove('dark');

// Listen for toggle changes (which includes `prefers-color-scheme` changes)
// and toggle the `dark` class accordingly.
toggle.addEventListener('colorschemechange', () => {
  body.classList.toggle('dark', toggle.mode === 'dark');
});

③ Using internal stylesheets for each color scheme

This approach allows you to define styles directly within your HTML using <style> tags, scoped to specific color schemes.

⚠️ Warning
Internal stylesheets do not benefit from the loading optimizations provided by <link> elements, which may increase the page's initial load time.

<head>
  <style media="(prefers-color-scheme: light)">
    body {
      background-color: #ffffff;
      color: #000000;
    }
  </style>
  <style media="(prefers-color-scheme: dark)">
    body {
      background-color: #000000;
      color: #ffffff;
    }
  </style>
  <script
    type="module"
    src="https://googlechromelabs.github.io/dark-mode-toggle/src/dark-mode-toggle.mjs"
  ></script>
</head>

Demo

See the custom element in action in the interactive demo. It shows four different kinds of synchronized <dark-mode-toggle>s. If you use Chrome on an Android device, pay attention to the address bar's theme color, and also note how the favicon changes.

Dark Light

Properties

Properties can be set directly on the custom element at creation time, or dynamically via JavaScript.

👉 Note that the dark and light icons are set via CSS variables, see Style Customization below.

Name Required Values Default Description
mode No Any of "dark" or "light" Defaults to whatever the user's preferred color scheme is according to prefers-color-scheme, or "light" if the user's browser doesn't support the media query. If set overrides the user's preferred color scheme.
appearance No Any of "toggle" or "switch" Defaults to "toggle". The "switch" appearance conveys the idea of a theme switcher (light/dark), whereas "toggle" conveys the idea of a dark mode toggle (on/off).
permanent No true if present Defaults to not remember the last choice. If present remembers the last selected mode ("dark" or "light"), which allows the user to permanently override their usual preferred color scheme.
legend No Any string Defaults to no legend. Any string value that represents the legend for the toggle or switch.
light No Any string Defaults to no label. Any string value that represents the label for the "light" mode.
dark No Any string Defaults to no label. Any string value that represents the label for the "dark" mode.
remember No Any string Defaults to no label. Any string value that represents the label for the "remember the last selected mode" functionality.

Events

  • colorschemechange: Fired when the color scheme gets changed.
  • permanentcolorscheme: Fired when the color scheme should be permanently remembered or not.

Complete Example

Interacting with the custom element:

/* On the page */
const darkModeToggle = document.querySelector('dark-mode-toggle');

// Set the mode to dark
darkModeToggle.mode = 'dark';
// Set the mode to light
darkModeToggle.mode = 'light';

// Set the legend to "Dark Mode"
darkModeToggle.legend = 'Dark Mode';
// Set the light label to "off"
darkModeToggle.light = 'off';
// Set the dark label to "on"
darkModeToggle.dark = 'on';

// Set the appearance to resemble a switch (theme: light/dark)
darkModeToggle.appearance = 'switch';
// Set the appearance to resemble a toggle (dark mode: on/off)
darkModeToggle.appearance = 'toggle';

// Set a "remember the last selected mode" label
darkModeToggle.remember = 'Remember this';

// Remember the user's last color scheme choice
darkModeToggle.setAttribute('permanent', '');
// Forget the user's last color scheme choice
darkModeToggle.removeAttribute('permanent');

Reacting on color scheme changes:

/* On the page */
document.addEventListener('colorschemechange', (e) => {
  console.log(`Color scheme changed to ${e.detail.colorScheme}.`);
});

Reacting on "remember the last selected mode" functionality changes:

/* On the page */
document.addEventListener('permanentcolorscheme', (e) => {
  console.log(
    `${e.detail.permanent ? 'R' : 'Not r'}emembering the last selected mode.`,
  );
});

Style Customization

You can style the custom element with ::part(). See the demo's CSS source code for some concrete examples. The exposed parts and their names can be seen below:

<form part="form">
  <fieldset part="fieldset">
    <legend part="legend"></legend>
    <input part="lightRadio" id="l" name="mode" type="radio" />
    <label part="lightLabel" for="l"></label>
    <input part="darkRadio" id="d" name="mode" type="radio" />
    <label part="darkLabel" for="d"></label>
    <input part="toggleCheckbox" id="t" type="checkbox" />
    <label part="toggleLabel" for="t"></label>
    <aside part="aside">
      <input part="permanentCheckbox" id="p" type="checkbox" />
      <label part="permanentLabel" for="p"></label>
    </aside>
  </fieldset>
</form>

Additionally, you can use a number of exposed CSS variables, as listed in the following:

| CSS Variable Name | Default | Description

Extension points exported contracts — how you extend this code

HTMLElementTagNameMap (Interface)
(no doc)
src/dark-mode-toggle.d.ts
GlobalEventHandlersEventMap (Interface)
(no doc)
src/dark-mode-toggle.d.ts

Core symbols most depended-on inside this repo

_dispatchEvent
called by 12
src/dark-mode-toggle.mjs
_updateThreeWayRadios
called by 10
src/dark-mode-toggle.mjs
installStringReflection
called by 7
src/dark-mode-toggle.mjs
_updateRadios
called by 7
src/dark-mode-toggle.mjs
_updateCheckbox
called by 7
src/dark-mode-toggle.mjs
_updateAppearance
called by 2
src/dark-mode-toggle.mjs
_updateMode
called by 2
src/dark-mode-toggle.mjs
installBoolReflection
called by 1
src/dark-mode-toggle.mjs

Shape

Method 13
Class 4
Function 4
Interface 2

Languages

TypeScript100%

Modules by API surface

src/dark-mode-toggle.mjs19 symbols
src/dark-mode-toggle.d.ts4 symbols

For agents

$ claude mcp add dark-mode-toggle \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact