Giter VIP home page Giter VIP logo

googlechromelabs / dark-mode-toggle Goto Github PK

View Code? Open in Web Editor NEW
1.2K 17.0 73.0 1.33 MB

A custom element that allows you to easily put a Dark Mode 🌒 toggle or switch on your site:

Home Page: https://googlechromelabs.github.io/dark-mode-toggle/demo/index.html

License: Apache License 2.0

JavaScript 80.74% Smarty 19.26%
dark-mode dark-theme dark-mode-switcher dark-mode-toggle dark-theme-switcher dark-theme-toggle prefers-color-scheme web-components custom-elements custom-elements-v1

dark-mode-toggle's Introduction

<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 two 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="common.css" />
  <link
    rel="stylesheet"
    href="light.css"
    media="(prefers-color-scheme: light)"
  />
  <link rel="stylesheet" href="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"
  />
  <p>Check out the dark mode toggle in the upper right corner!</p>
</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="common.css" />
  <noscript id="dark-mode-toggle-stylesheets">
    <link
      rel="stylesheet"
      href="light.css"
      media="(prefers-color-scheme: light)"
    />
    <link
      rel="stylesheet"
      href="dark.css"
      media="(prefers-color-scheme: dark)"
    />
  </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');
});

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
--dark-mode-toggle-light-icon No icon The icon for the light state in background-image: notation.
--dark-mode-toggle-dark-icon No icon The icon for the dark state in background-image: notation.
--dark-mode-toggle-icon-size 1rem The icon size in CSS length data type notation.
--dark-mode-toggle-remember-icon-checked No icon The icon for the checked "remember the last selected mode" functionality in background-image: notation.
--dark-mode-toggle-remember-icon-unchecked No icon The icon for the unchecked "remember the last selected mode" functionality in background-image: notation.
--dark-mode-toggle-color User-Agent stylesheet text color The main text color in color: notation.
--dark-mode-toggle-background-color User-Agent stylesheet background color The main background color in background-color: notation.
--dark-mode-toggle-legend-font User-Agent <legend> font The font of the legend in shorthand font: notation.
--dark-mode-toggle-label-font User-Agent <label> font The font of the labels in shorthand font: notation.
--dark-mode-toggle-remember-font User-Agent <label> font The font of the "remember the last selected mode" functionality label in shorthand font: notation.
--dark-mode-toggle-icon-filter No filter The filter for the dark icon (so you can use all black or all white icons and just invert one of them) in filter: notation.
--dark-mode-toggle-remember-filter No filter The filter for the "remember the last selected mode" functionality icon (so you can use all black or all white icons and just invert one of them) in filter: notation.
--dark-mode-toggle-active-mode-background-color No background color The background color for the currently active mode in background-color: notation.

Hacking on <dark-mode-toggle>

The core custom element code lives in src/dark-mode-toggle.mjs. You can start hacking and testing your changes by running npm run start and then navigating to http://localhost:8080/demo/. No build step required 🎉, this happens automatically upon npm publishing. If for whatever reason you want to build locally, run npm run build. You can lint by running npm run lint.

The HTML and the CSS used by <dark-mode-toggle> is hard-coded as a template literal in the file src/dark-mode-toggle.mjs. For optimal performance, the contents of this literal are hand-minified. If you need to tweak the HTML or the CSS, find the unminified template literal contents in src/template-contents.tpl and copy them over to src/dark-mode-toggle.mjs. Once your changes are done, commit them to both the *.tpl file (in unminified form) and the *.mjs file (in minified form).

(This is actually just making a strong argument for CSS Modules and HTML Modules that would allow for proper tools integration).

Proudly used on…

  • v8.dev: V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.

    v8.dev in light mode

    v8.dev in dark mode

  • Your site here…

Notes

This is not an official Google product.

Acknowledgements

Thanks to all contributors for making <dark-mode-toggle> even better! Usage video by Tomek Sułkowski.

License

Copyright 2019 Google LLC

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

dark-mode-toggle's People

Contributors

coliff avatar dependabot[bot] avatar erikfontanel avatar haocen avatar isti115 avatar m417z avatar mathiasbynens avatar notwoods avatar rowan-m avatar rreverser avatar tomayac avatar zarthus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dark-mode-toggle's Issues

CSS custom property to change the icon size

Hey @tomayac , thank you for this custom element! I've started using it on a remake on my site and I really like it, it's been fun and easy to use! 🎉

I'm just wondering if there's a way to change the size of the icons? I see that there are CSS custom properties to change the font size of the labels, but I couldn't find one for the icons (please correct me if I'm wrong, I might have just missed it 😅 ).

I see from dark-mode-toggle.js#L127-130 that the icons have a size of 1rem, maybe a --dark-mode-toggle-icon-size custom property to customize this value?

Thanks! 😄

Reloading in the demo in dark mode still causes an initial flash of the light theme.

Can this be improved so that's there's no flash? I was considering your script because is similar to the way I implemented it on my site that is with a class that overrides custom styles but I have this very same problem which is kind of annoying for users in particular for dark mode as it blinds you for a sec. I forgot to mention: tested this on the demo site with remember preference on.

Minified version is broken

Currently terser is configured to minify all properties, and ends up even minifying access to attribute reflections.

For example:

this.permanent = event.detail.permanent;
this.permanentCheckbox.checked = this.permanent;

is currently minified to

        (this.g = e.detail.g), (this.p.checked = this.g);

so it ends up accessing invalid properties, and same in other places.

Can't get to work

Hey,

I've pretty much copied the examples and put the dark-mode-toggle markup into my code but I see absolutely no output. The element has no width or height or anything. Any ideas where I may be going wrong?

Icon Flash on Mouse Hover

When using custom PNGs for the light/dark, I'm seeing a brief flash of the icon when the mouse hovers over the icon and when moving off of the icon. Using the OOTB icons this doesn't happen.

dark-mode-toggle {
  position: absolute;
  top: 0.5rem;
  right: 1rem;
  --dark-mode-toggle-light-icon: url(/assets/moon.png);
  --dark-mode-toggle-dark-icon: url(/assets/sun.png);
  --dark-mode-toggle-icon-size: 2rem;
  --dark-mode-toggle-icon-filter: invert(100%);
  transform:translate3d(0, 0, 0);
}

Not sure why this would be happening with custom PNGs.

Add aria-label for lighthouse

When running the Chrome lighthouse, I am getting the following accessibility issue:

image

image

Could you please easer hard code an aria-label value or pass it down as a property?

Apart from `light` and `dark`, add a `system` option

Is there any way (currently) or are there any plans on adding a system theme option that would just reflect the system and not override it? Or do I have to somehow make a custom one that clears the localStorage?

dark mode switch error

When dark mode is active, when I refresh the page, it loads "LIGHT" first and then goes into dark mode. how can i fix this. If dark is selected, install dark.
it seems a little silly to start "light" first and switch to darkness immediately. I wonder if there is an error in my codes. I'm waiting for your help
you understand what I want to say from the video.
video

<meta name="color-scheme" content="dark light"/>
<meta name="theme-color" content="rgb(174, 129, 7)"/>
<link rel="icon" content="">
<link rel="stylesheet" href="'dark-mode/styles/light.css'" media="(prefers-color-scheme: light)">
<link rel="stylesheet" href="'dark-mode/styles/dark.css'" media="(prefers-color-scheme: dark)">
<link rel="stylesheet" href="'dark-mode/styles/common.css'">
<script type="module" src="'dark-mode/scripts/dark-mode-toggle.mjs'"></script>
<script type="module" src="'dark-mode/scripts/dark-mode-toggle-playground.mjs'"></script>
script
    if (window.matchMedia('(prefers-color-scheme)').media === 'not all') {
        document.documentElement.style.display = 'none';
        document.head.insertAdjacentHTML(
            'beforeend',
            '<link rel="stylesheet" href="dark-mode/styles/light.css" onload="document.documentElement.style.display = ``">'
        );
    }
</script>
<aside><dark-mode-toggle id="dark-mode-toggle-2" permanent></dark-mode-toggle></aside>

Implement saving light/dark mode

Hello, could you tell me how can I implement saving light/dark mode on my site like here (https://v8.dev/) without "Remember" checkbox? Adding "permanent" parameter doesn't help. Though this parameter is set in this website code and theme is saved without the checkbox.

Extra unnecessary right margin

When not setting a legend on the component there is still a right margin relative to the icon, see the following screenshot:

image

When no legends are set should not the icon be centred with no extra unnecessary margin?

EDIT: Also, why is the fieldset so wide compared to the icon, could we make the fieldset the same area than the icon or add a CSS vars to customise the fieldset? My goal here would be to set the width and height of the fieldset to 32px to match the other icons contained within mwc-button-icon.

image

Transition question

First off, this is dope. Thank you.

I have a question about smooth transitions. I'm not a very experienced front-end developer, I'm a photographer trying to build my own stuff to avoid hosting fees while times are tough, and using the spare time to learn some html/css/js.

I stumbled across this on web.dev when trying how to get a theme for a static site generator to default the OS light/dark but remember overwritten user controls.

In that article, you have..
`body {
--duration: 0.5s;
--timing: ease;

color: var(--color);
background-color: var(--background-color);

transition:
color var(--duration) var(--timing),
background-color var(--duration) var(--timing);
}`
But there is no mention of it in the github version. With it still applied, the page blips from light to dark when the mode is permanent. I was curious what I need to look at specifically to fix that.

Keep light mode after changing page for Wordpress Theme

I noticed that if the person is in light mode and switches to dark mode and refreshes the page it continues in dark mode, now if the person is in dark mode and switches to light and refreshes the page it does not work page back for dark.

I use a select button

image

Can you help me?

// Get current theme
var theme = localStorage.getItem( 'theme' );
// Set defaults if theme is not defined.
if ( ! theme ) {
  localStorage.setItem( 'theme', 'light' );
  theme = 'light';
}
// Add theme to the body.
document.body.classList.add( theme );

// Handle onClick events
document.getElementById( 'theme-toggle' ).addEventListener( 'click', () => {
  // Cleanup classes from body.
  document.body.classList.remove( 'light' );
  document.body.classList.remove( 'dark' );
  // Change the theme.
  theme = ( theme === 'light' ) ? 'dark' : 'light';
  // Save the theme.
  localStorage.setItem( 'theme', theme );
  // Apply the theme.
  document.body.classList.add( theme );
});

if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
	document.body.classList.remove( 'light' );
	document.body.classList.remove( 'dark' );
    var theme = 'dark';
	localStorage.setItem( 'theme', theme );
	document.body.classList.add( theme );
}
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
	document.body.classList.remove( 'light' );
	document.body.classList.remove( 'dark' );
    var newColorScheme = event.matches ? "dark" : "light";
	localStorage.setItem( 'theme', newColorScheme );
	document.body.classList.add( newColorScheme );
});

Vertical spacing on checkbox label is off

Thanks for making this handy tool. It's really easy to just plug in and get working.

The icon needs a bit of bottom margin so that it is horizontally aligned with the label text:

spacing

The margin on label::before should be something like 0 .5rem .16rem 0, not 0 .5rem 0 0.

Alternatively, I think there's a way to put both elements in a flex container and align-content: center.

I can't override it myself since it is in a shadow dom.

Problems styling ::parts and pseudo elements such as ::before

Hi, well its been interesting to learn about Shadow CSS and ::parts but how can I style :: before and ::after using parts? It seems is not possible to target both at the same time. In my case I need to set different values for icons in the select button/form for width and height so it seems current variables are not enough. Maybe the code related to the toggle/switch could be further simplified.

[feature request] support SRI (sub resources integrity)

Currently if CSP (content security policy) does not already include unsafe-inline, client browser will refuse to load inline styles from this web component.

Due to the way this project is built it is not very easy for developers to get around this limitation.

Unable to Load png files when running on Github Pages

It is somewhat weird that the png files are loading when I ran locally but were unable to load properly after committing the code to Github and ran using Github pages. (I am able to use the button but it is transparent🤷‍♂️.)
I am unable to figure out what is happening?

Link to Source Code

Local The moon png in the navigation bar
image

Github Pages
image

Code Snippets:
CSS
image

HTML
image

HEAD
image

Files are .mjs, but seem to be hand-written UMD

Is there a reason to do UMD style at all? A module defined a scope, so you don't need a function scope to keep from accidentally creating globals. If you did, you could just use a block {} anyway.

Also, both the source file and dist file have .mjs extensions even though neither has an import or export. Is there a reason to check-in the minified file? It can be published to npm and available via unpkg.com without being checked in.

Failed to load module script: The server responded

hi i wanted to download the source code and run it on localhost but unfortunately i get this error every time. what's the problem ? how can i solve?

no changes have been made to the file I get this error even when I want to use the demos

Failed to load module script: The server responded with a non-JavaScript MIME type of "". Strict MIME type checking is enforced for module scripts per HTML spec.

Declare as a Web Component

Hi GoogleChromeLabs,

I am no expert in web dev or web components, but in my current project when using the dark-mode-toggle, lit-plugin is throwing the following warning message:

Unknown tag <dark-mode-toggle>.
  Check that you've imported the element, and that it's declared on the HTMLElementTagNameMap. If it can't be imported, consider adding it to the 'globalTags' plugin configuration or disabling the 'no-unknown-tag' rule.lit-plugin(no-unknown-tag-name)(2322)

Is there anything you could do to fix the above?

Kind regards,
Alex

Any way to toggle light/dark native widgets when using <meta name='color-scheme' content='light dark'> ?

I added to my page so that the browser would draw dark scrollbars and other native widgets in dark mode. When I have the browser in dark mode and use the dark-mode-toggle switch to change my website to light mode, the widgets stay in dark mode. And vice versa... with browser in light mode and website toggled to dark mode, browser continues using light widgets. Is there any way to also toggle the meta tag so that native widgets follow the current theme? Not sure if it's possible but thought I would ask. Light widgets look OK in dark mode, but dark widgets look bad in light mode, so for now I removed the meta line to force light widgets.

dark-mode-toggle and SVG

we've experimented with your AMP variation. our planned site heavily uses SVG (rather than PNG/JPG). the dark-mode 'bleeds' thru the SVGs. we have a sample to share if you would like to see this use case. we would be willing to change our approach to using SVG linearGradient and radialGradient to work with dark-mode-toggle, but are uncertain how to do so. let me know if you are willing to collaborate with us on supporting SVGs and dark-mode-toggle.
/jay gray

Consider aria-label="auto" aria-live="polite"

I am a junior Dev and While implementing dark-mode-toggle and my other study from the below Google article I came across
aria-label="auto" aria-live="polite" for theme component.

https://web.dev/building-a-theme-switch-component/

In this, we keep the aria-label auto by default and change it to "light" or "dark" based on our toggle switch.
Also aria-live="polite" seems to add up.

If possible kindly have a look at these enhancements if deemed appropriate.

Class based

I built practically the same system for a site i'm working on but I actually really like some of the ideas you have put in here. My issue is that my dark/light styling is controlled via a high-level class. Could this be tweaked to allow a top-level class to be used rather than multiple stylesheets?

Thanks

Extra margin

I have my toggle set up as a toggle and the permanent attribute set. The icon I am using has a 1x1 aspect but I get some random margin on the right and bottom so the width doesn't match the height?

How can I remove these margins?

Also a way to be able to remove or alter the style of the focus styles would be useful.

Flashes when system prefers dark, but light theme is toggled

This even happens on the demo site. https://googlechromelabs.github.io/dark-mode-toggle/demo/index.html

Tested on both Chrome and Firefox.

System must be configured to prefer dark, then light theme must be toggled on and remembered in the site. On page change or refresh, sometimes you'll get a frame or two where the dark theme is rendered first, then it flips over to the light theme as expected. With the demo site, because there's a transition enabled, you get the dark theme fading back into the light theme.

Hopefully a workaround is found for this!

dark-mode-toggle with React

Hi,

A DOMException error occurs when <dark-mode-toggle> is used in React apps.

Failed to construct 'CustomElement': The result must not have attributes

I think it occurs when document.createElement has been called.

The error would be solved if the DOM related tasks move from constructor to connectedCallback, but I am not sure this is an appropriate change for dark-mode-toggle.

prefer-color-scheme overrides permanent ?

Hi,

Firstly, great post at web.dev + good job with the element.

Just running into a wee issue. We have the following HTML,

<dark-mode-toggle appearance="toggle" permanent dark="Dark Theme" light="Light Theme"></dark-mode-toggle>

When the user toggles the color scheme, either via OS or via Chrome dev tools, the permanent setting is lost. Not sure if I got something wrong or I missed some detail or is this behaviour expected?

Example scenario: User OS theme set to dark. User visits website, dark theme loads by default. User changes website setting to light. User then changes OS them from dark to light and back to dark. The website switches to dark theme.

Also, is it possible to remove the outline in CSS (example would be handy), or even better add a ripple effect? Our website uses mdc-web-components. An example with a material text button as toggle would be super handy.

Cheers.

A few issues

I have followed and read your tutorial at https://web.dev/prefers-color-scheme/ with great interest. It is a really nice tutorial for newbie like me, so many thanks for that.

Also, I decided to go the lazy/easy route and simply use your component rather than implementing all the logic behind for the theme switch.

My application is based on material web components - https://github.com/material-components/material-components-web-components - and style wise it does not really blend in, see the following screenshot:

image

As you can see my language button got a ripple around it, it is in fact a button when your component is just an icon, you can also see that the size is different, I have tried to see if I could wrap your component around a mwc-icon-button but I did not manage to get it to work.

This is the code that I have so far:

    <mwc-top-app-bar-fixed
            @MDCTopAppBar:nav=${() => (this.drawer.open = !this.drawer.open)}
          >
            <mwc-icon-button
              slot="navigationIcon"
              icon="menu"
              id="hamburger"
            ></mwc-icon-button>
            <h3 slot="title">Evil Corp</h3>
            <mwc-icon-button
              slot="actionItems"
              icon="languages"
            ></mwc-icon-button>
            <dark-mode-toggle
              slot="actionItems"
              appearance="toggle"
              permanent
            ></dark-mode-toggle>
            <!-- <mwc-icon-button-toggle
              onIcon="nights_stay"
              offIcon="wb_sunny"
              slot="actionItems"
            ></mwc-icon-button-toggle> -->
            <div class="navbar">
              <nav class="flex-container">
                <my-menu class="navbar-nav"></my-menu>
              </nav>
              <mwc-linear-progress></mwc-linear-progress>
            </div>
      </mwc-top-app-bar-fixed>

Also,I have notice that when my preferred theme is dark and I set the component to remember the choice when I visit the page again - refresh the page - it transition from dark theme to white theme, is this a know issue?

Remember

Hey,

I find that the remember feature doesn't seem to work for me. I load the site with my OS appearance set to light, the site shows in light, I then toggle to dark which the dark-mode-toggle and click remember. I see the local storage key getting set. I refresh the page and it shows in light, the local storage key also switched the light. Any ideas?

Also, once the above is working, what does it do if you switch the OS mode to be equal to the permanent setting, does this remove the local storage key as they will match and are no longer required? This would be a cool feature to have.

Flash of wrong styles

Great project overall, its a nice inspiration!

All solutions I discovered on the web with a permenent switch and also my own custom code suffer from a flash of the wrong styles at some point before the styles accoring to localStorage setting is applied. This happens in latest Chrome, but not in Desktop and Mobile Safari.

your regular demo does (on page reload) and v8.dev also, only your barebones demo seems fast enough

is it just not possible to avoid a flash (e.g. white background flash before dark background gets applied) without blocking the rendering or hiding the page or do have a suggestion?

customElements is not defined

Hello @tomayac,

In old browsers like Firefox 52, there is no support for Custom Elements. I'm using Webpack with Babel and I can't find a plugin to support Custom Elements. So i suggest you to do nothing if customElements is not defined.

// Do nothing if `customElements` does not exist. 
if (!window.customElements) return;

Thank you in advance !

Support for using as a React component

Thanks for this awesome little widget, I've looked at quite a few dark mode toggles and I like the "switch" version of this one the most so far!

I would like to use it as a React component, so I'd like to ask if submitting such an abstraction layer over the current web component would be accepted here as a PR, or in case not, whether you'd be happy with me creating a separate wrapper package for it?

(I'd also like to include slider.css, moon.svg and sun.svg, but they aren't accessible from simply linking this package as a dependency, so in that case I would copy them and do my best to annotate them properly according to the Apache-2.0 license of this repo.)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.