Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support system-/browser-level dark mode #234

Open
rmccue opened this issue Oct 10, 2019 · 22 comments · May be fixed by #560, #858 or #1328
Open

Support system-/browser-level dark mode #234

rmccue opened this issue Oct 10, 2019 · 22 comments · May be fixed by #560, #858 or #1328
Labels
enhancement status: needs discussion Issues that need more discussion before they can be properly triaged.

Comments

@rmccue
Copy link

rmccue commented Oct 10, 2019

Just the Docs has a great dark mode, but it's completely modal at build time. It would be great if it could be configured to use the prefers-color-scheme: dark media query to dynamically support dark mode depending on the user's preferences.

One possible solution to this would be to use CSS variables rather than SCSS variables where possible, and have these then cascade down from :root.

@pdmosses
Copy link
Contributor

@pmarsceill would the suggested solution (using CSS variable) be compatible with the overall implementation of styling in Just the Docs?

Also, PR #302 implements a button to toggle dark mode. Perhaps that would make this proposed enhancement redundant?

pdmosses added a commit to pdmosses/just-the-docs that referenced this issue Oct 18, 2020
Implement just-the-docs#234
- Use media queries to choose light or dark color scheme
- Update docs and configuration
@pdmosses pdmosses mentioned this issue Oct 18, 2020
@pdmosses pdmosses linked a pull request Oct 18, 2020 that will close this issue
@henryiii
Copy link
Contributor

henryiii commented Jan 29, 2021

This trick actually works pretty well on the current version:

cat _includes/js/custom.js
window.matchMedia('(prefers-color-scheme: dark)')
      .addEventListener('change', event => {
  if (event.matches) {
      jtd.setTheme('dark');
  } else {
      jtd.setTheme('light');
  }
});

if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
    jtd.setTheme('dark');
}

Implemented in scikit-hep/scikit-hep.github.io#114

Edit: the last line should be conditional.

@pdmosses
Copy link
Contributor

pdmosses commented Jan 30, 2021

@henryiii thanks for this! Your 'trick' looks very clean, and appears to work perfectly. It is also much simpler than my SCSS-based #464.

Would you like to submit a PR to add your code to just-the-docs.js? Activation will need to be conditional on a configuration option, I think.

To address the point raised by @pmarsceill in a comment on PR #302: the name of the default color scheme in the js could be {{ site.color_scheme }} instead of light; using (e.g.) {{ site.darker_color_scheme }} instead of dark would make that name configurable too.

@SageofPHY6Paths
Copy link

SageofPHY6Paths commented Jul 21, 2022

@henryiii your solution works well for those whose prefers-color-scheme is dark.

But can you mix it with the toggle given in the dark mode button in Configuration and Customization pages

<button class="btn js-toggle-dark-mode">Preview dark color scheme</button>

<script>
const toggleDarkMode = document.querySelector('.js-toggle-dark-mode');

jtd.addEvent(toggleDarkMode, 'click', function(){
  if (jtd.getTheme() === 'dark') {
    jtd.setTheme('light');
    toggleDarkMode.textContent = 'Preview dark color scheme';
  } else {
    jtd.setTheme('dark');
    toggleDarkMode.textContent = 'Return to the light side';
  }
});
</script>

to create a toggle that remembers the preference? I don't know the exact syntax but I believe you can do it simply by using localStorage.setItem(); instead of prefers-color-scheme. I think a bit care must be taken so that there are no flashes when the toggle is pressed.
Related: #885
@pdmosses

@mattxwang
Copy link
Member

mattxwang commented Aug 23, 2022

Okay, I've given it some thought - I think what I'd like to see (from personal experience) is a combination of various approaches already proposed:

  • have a visible toggle, that theme users can opt-in / opt-out of displaying - opting out forces the user's preferred color scheme
  • if the user has prefers-color-scheme, that should override the default toggle position for the site. however, we should still allow the user to toggle, and if they've toggled, prefer that over the browser. We can periodically reset this on release if we'd wish, or suggest a mechanism for theme developers to refresh the toggle.

I think user toggles are important because many users have preferences that can supersede their system setting. The more common case is a dark mode website when the user has a light mode system, but I've also seen the inverse happen on occasion.

In other words, let's take the approach in #560, and add a user-visible toggle (similar to #302).

If we don't like the idea of a user toggle, I also don't mind merging in #560 first and addressing this down the line, though I do think it's an important feature.

Can I get some opinions on this? @pdmosses @henryiii @Alexander-Taran.

@mattxwang
Copy link
Member

Seems like @captn3m0 is also someone good to ping since one of their projects requested this feature!

@Alexander-Taran
Copy link

@mattxwang I like this idea.
Having a default that follows system settings with a clear ability to override.

@SageofPHY6Paths
Copy link

@mattxwang this https://github.com/SageofthePHY6Paths/hinduismdebunked.com/blob/master/_layouts/default.html might be useful. @ArmoredVortex succeeded in adding a toggle that stores as a cookie.

@pdmosses
Copy link
Contributor

@mattxwang In connection with #560, I noticed flashes of unstyled content (FOUCs) when testing in Firefox. A recent comment indicates that this is still a significant irritation for Firefox users.

I'm not a Firefox user (except when Safari messes up on a website aimed at Explorer users 🙄) but unless there's a reliable and easy to use workaround that suppresses the FOUC, I think we should try to avoid adding a feature that don't work properly on particular browsers.

@Alexander-Taran how about your #858 – would that avoid FOUCs in Firefox? BTW, if you update your PR to v0.4.0.rc1, it would generate a preview on Netlify, which would make it easier to test and review.

@pdmosses
Copy link
Contributor

@mattxwang The toggle from #302 is shown on https://aronsommer.github.io/just-the-docs-dmt/ in the upper right corner, which is where we usually display any aux links. Could the toggle be moved to the top of the nav panel, below the title/logo?

BTW, I'd prefer a symbolic toggle (perhaps configurable?) instead of a button with a text.

@pdmosses
Copy link
Contributor

@mattxwang GitHub has surely put a lot of expert design effort into their own website. AFAIK, most of it is provided by their Primer framework, which is open source (with an MIT license). I suggest to take a look at how they switch between light and dark mode.

They have advice on using Primer with Jekyll. Presumably @pmarsceill knows all about Primer, and could advise on how compatible it is with our current design.

Unfortunately, Primer doesn't include the PrettyLights/TreeLights highlighting that GitHub uses when displaying source code, so I don't think it would help us with making our code highlighting closer to GitHub's.

@Alexander-Taran
Copy link

Alexander-Taran commented Aug 29, 2022

@Alexander-Taran how about your #858 – would that avoid FOUCs in Firefox? BTW, if you update your PR to v0.4.0.rc1, it would generate a preview on Netlify, which would make it easier to test and review.

There is no FOUC. But it does not support IE.
My PR is a reference only. It is the simplest of all temporary solutions.
We did put it in production and there are no complaints.

@pdmosses
Copy link
Contributor

@Alexander-Taran thanks for updating #858, so we have the Netlify preview.

I don't see any FOUCs in a fresh installation of Firefox. And I very much like the simplicity of #858!

I'm not an IE user; does it have no effect at all on IE, or is it only the automatic refreshing of open windows that IE doesn't do?

@Alexander-Taran
Copy link

I'm not an IE user; does it have no effect at all on IE, or is it only the automatic refreshing of open windows that IE doesn't do?

IE will not have styling at all because both stylesheets have a media-query attached to them. So no stylesheet will be matched by IE. Which is by design. Time to let it go.

@simonebortolin
Copy link
Contributor

simonebortolin commented Aug 31, 2022

I have implemented this solution on my site:

if(localStorage.getItem("color-scheme") === null) {
    const newColorScheme = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? "dark" : "light";
    const newTextScheme = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? "Light mode" : "Dark mode";
    jtd.setTheme(newColorScheme);
    localStorage.setItem("color-scheme",newColorScheme);
    localStorage.setItem("text-scheme",newTextScheme);
    window.addEventListener('load', function () {
        toggleDarkMode.textContent = newTextScheme; 
    });
} else {
    jtd.setTheme(localStorage.getItem("color-scheme"));
    window.addEventListener('load', function () {
        toggleDarkMode.textContent = localStorage.getItem("text-scheme"); 
    });
}

window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
    if(localStorage.getItem("color-scheme") === null) {
        const newColorScheme = event.matches ? "dark" : "light";
        const newTextScheme = event.matches ? "Light mode" : "Dark mode";
        jtd.setTheme(newColorScheme);
        toggleDarkMode.textContent = newTextScheme; 
        localStorage.setItem("color-scheme",newColorScheme);
        localStorage.setItem("text-scheme",newTextScheme);
    }
});


const toggleDarkMode = document.querySelector('.js-toggle-dark-mode'); 
jtd.addEvent(toggleDarkMode, 'click', function(){ 
    const newColorScheme = jtd.getTheme() !== 'dark' ? "dark" : "light";
    const newTextScheme = jtd.getTheme() !== 'dark' ? "Light mode" : "Dark mode";
    jtd.setTheme(newColorScheme);
    toggleDarkMode.textContent = newTextScheme; 
    localStorage.setItem("color-scheme",newColorScheme);
    localStorage.setItem("text-scheme",newTextScheme);
});

this solution does not work on IE, but it does not bother me as it is obsolete, although one can think of using <!--[if IE]>
solution #858 fixed by me (https://github.com/simonebortolin/just-the-docs/tree/prefers-color-scheme) in my opinion is the simplest solution, which can be integrated with the script above

@mattxwang
Copy link
Member

Looking to centralize the conversation on this in this issue if possible!

Basically - if (any) PR is updated or opened that:

  • supports defaults based off of prefers-color-scheme
  • and, has some sort of user-defined toggle that overrides prefers-color-scheme
  • and, documents how developers can use this feature / what the defaults are
    • things to consider (but not necessary):
      • how would the developer opt-out of the prefers-color-scheme behaviour
      • how would the developer opt-out of the toggle

I'd be happy to review and merge it, possibly even for v0.4.0 (if not, for sure in the next release after).

cc: @Alexander-Taran for #858


To answer some questions in this thread (from my perspective as a maintainer):

In connection with #560, I noticed flashes of unstyled content (FOUCs) when testing in Firefox. A recent comment indicates that this is still a significant irritation for Firefox users.

It seems like a <script> hack in the thread can help us:

<!DOCTYPE html>
<link rel="stylesheet" href="[https://software.hixie.ch/utilities/cgi/test-tools/delayed-file?pause=2&mime=text/css&text=body+{+color:+red+}](https://software.hixie.ch/utilities/cgi/test-tools/delayed-file?pause=2&mime=text%2Fcss&text=body+%7B+color%3A+red+%7D)">
<script>/**/</script>
<script defer src="data:application/javascript,onload = function() {alert('load: ' + getComputedStyle(document.body).color);}; alert('after: ' + getComputedStyle(document.body).color)"></script>

If we continue this PR, we should investigate if that resolves our specific problem. My worry is that this one bug report is actually many different Firefox bugs, and it's hard to disentangle what affects what.

The toggle from #302 is shown on https://aronsommer.github.io/just-the-docs-dmt/ in the upper right corner, which is where we usually display any aux links. Could the toggle be moved to the top of the nav panel, below the title/logo?

BTW, I'd prefer a symbolic toggle (perhaps configurable?) instead of a button with a text.

I generally prefer the upper-right corner for these sorts of things, since it tends to be the standard; see: CRA docs and Jest docs (which I both believe are built with docusaurus). To counter my own point, the beta react docs are putting them under the sidenav. My general thought on this is that the default UX should be what users expect, and I typically expect the toggle to be in the top right (in desktop) and vertically centered (in a mobile hamburger).

Happy to be overruled on this one, I don't have a particularly strong opinion.

GitHub has surely put a lot of expert design effort into their own website. AFAIK, most of it is provided by their Primer framework, which is open source (with an MIT license). I suggest to take a look at how they switch between light and dark mode.

At the user level, GitHub supports autoswitching and user-configuration. I think this is the way to move forward (see my approach above).

paraphrasing,

do we need to support IE?

My personal take is no - I'm happy to drop IE support (even big CSS "vendors" like Bootstrap have, and now Edge uses Chromium under the hood). Okay adding documentation to make that clear if it's necessary.

@pdmosses
Copy link
Contributor

Instead of a normal toggle button, GitHub repo pages have a drop-down menu button in the upper-right corner, including a link to a Settings page. To switch between light, dark, and auto, we need to open https://github.com/settings/appearance. That page also allows setting any of their color schemes for light and dark use (with a very cool visualisation of their appearance).

But if we expect that visitors to a website don't need to change the appearance preferences so often, what is the motivation for displaying a toggle or drop-down menu on every page? Couldn't it be restricted to the home page? If JtD sites have a dedicated page that mimics the GH appearance settings pane, we could put a link to it at the top of the home page. We already have a link to the home page at the top left of every page, so getting to the settings page would only take one extra click.

@pdmosses
Copy link
Contributor

To answer some questions in this thread (from my perspective as a maintainer):

In connection with #560, I noticed flashes of unstyled content (FOUCs) when testing in Firefox. A recent comment indicates that this is still a significant irritation for Firefox users.

It seems like a <script> hack in the thread can help us:
[...]
If we continue this PR, we should investigate if that resolves our specific problem. My worry is that this one bug report is actually many different Firefox bugs, and it's hard to disentangle what affects what.

@henryiii If you could resolve the current conflicts in PR #560, we'd be able to check whether any FOUCs appear when using Firefox to browse the Netlify preview.

@mattxwang The Netlify preview of PR #858 appears to work well, without any FOUCs on Firefox (and without introducing a hidden dependence on a script hack, which I'd prefer to avoid).

I think it would be helpful if @simonebortolin could submit a PR based on https://github.com/simonebortolin/just-the-docs/tree/prefers-color-scheme (or merge that branch into @Alexander-Taran's PR #858) so that we get a preview of it, to facilitate reviewing and comparison with #560.

PR #464 led to excessively large CSS files, and it doesn't appear to have any advantages over #858, so I'll now close it.

@simonebortolin
Copy link
Contributor

In reply of @pdmosses at #966

As @mattxwang mentioned, we also want this feature to be statically configurable. To avoid breaking existing sites that only use a single color scheme, the feature should be off by default.

For sites that have more than the light and dark schemes provided by JtD, I think it would also be useful to be able to set the names of the schemes used for the light and dark preferences. Note that W3C doesn't distinguish between preference for "light" and no preference, so the existing color_scheme setting can be used for the light preference.

Moreover, we'll also need to support some way of dynamically setting or toggling a website between the light and dark schemes. Let's discuss that further in #234.

if I understand correctly, you want JtD to have 3 possibilities:

  • fixed (light or dark) I imagine set to the colour_scheme flag (light or dark) of _config.yml
  • auto, also I imagine set to the colour_scheme flag (auto) of _config.yml
  • manual (light, dark, auto) with web storage/cookie, the latter done with a dropdown/popup menu/dedicated page in the style of https://github.com/settings/appearance, with a flag manual on colour_scheme that enables scripts and pop-ups?

If the manual configurator part is left to developers as proposed by @mattxwang:

and, documents how developers can use this feature / what the defaults are

  • things to consider (but not necessary):

    • how would the developer opt-out of the prefers-color-scheme behaviour
    • how would the developer opt-out of the toggle

If I understood everything, it's not difficult at all. I might even do the PR next week.

But if we expect that visitors to a website don't need to change the appearance preferences so often, what is the motivation for displaying a toggle or drop-down menu on every page? Couldn't it be restricted to the home page? If JtD sites have a dedicated page that mimics the GH appearance settings pane, we could put a link to it at the top of the home page. We already have a link to the home page at the top left of every page, so getting to the settings page would only take one extra click.

A simple motivation is, for example, whether the user wants to look at pages with many images with a white theme because the images look worse with a dark theme, and pages with only text with a dark theme, to relax the eyes.

Another motivation is PCs used by multiple users

@mattxwang The Netlify preview of PR #858 appears to work well, without any FOUCs on Firefox (and without introducing a hidden dependence on a script hack, which I'd prefer to avoid).

I think that bug will always occur in the case of a theme change saved in local storage.

@henryiii
Copy link
Contributor

My favorite UI implementation of a three-way switch is at https://peps.python.org. It's got a three-way icon; one for auto, one for dark, and one for light. It's simple, clear, and unobtrusive.

@vijaya-lakshmi-venkatraman

HI
Is this feature released?

@mattxwang
Copy link
Member

HI Is this feature released?

Hi @vijaya-lakshmi-venkatraman, it's still under development; the latest attempt has been #1086. In the meantime, you can implement a lighter version of it using jtd.setTheme, or looking at the various PRs that are linked to this issue.

@mattxwang mattxwang linked a pull request Aug 22, 2023 that will close this issue
matttbe added a commit to mux99/mptcp.dev that referenced this issue Apr 11, 2024
Instead of putting the JS script in the middle of the HTML page and
changing what has already been displayed.

Link: just-the-docs/just-the-docs#234 (comment)
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment