pradyunsg/furo

Customization to select light/dark/dual mode

Closed this issue ยท 21 comments

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Currently, I think by default furo adapts to OS (or browser) settings to display light/dark mode. I'll be nice if we can choose to render only light mode, or only dark mode, or both like the present default.

Describe the solution you'd like
A clear and concise description of what you want to happen.

Something like a setting in conf.py for the preferred action?

html_theme_options = {
    "theme-color": light/dark/dual,
}

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Stick with the current default. :)

Sounds fair!

I'll note that I'd rather to make this configurable by the end-user; i.e. a part of the generated website and controlled by the user on a per-device-browser basis. That's more common and is usually what the users expect anyway.

Any bright ideas for where to put the toggle on the screen, on each resolution/breakpoint?

on each resolution/breakpoint?

๐Ÿ˜„ looking at the timestamp it's plausible that this leaked form a pip's discussion?

BTW, if the site's author uses images with transparent background, only light or dark would work, so it'd be nice if perse can hint that the other mode is broken by hardcoding the working mode.

BTW, if the site's author uses images with transparent background, only light or dark would work, so it'd be nice if perse can hint that the other mode is broken by hardcoding the working mode.

If you'd like to make additional requests, please do so in a new issue. :)

In #44, the suggestion is to add it to the right sidebar.

Currently, Furo completely disables the right sidebar if there is no TOC to show, since that's... well, the only thing in the right sidebar, and an empty drawer is useless. :)

I was going to say right side bar a la Docker, but @pradyunsg made the point I was about to make. How about give it as an option? Below the logo icon or at the bottom of the left sidebar

how about somewhere in the left sidebar (above or below the search box)? it's the kind of control that does not have to be visible when the left sidebar is not visible.

This rust guide floats theirs in a bar at the top but we could make this button float in the top left of the content rather than in a bar? https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html

Another option is at the bottom of the page with the footer.

The bar at the top only shows up on small resolutions, and is hidden on wider screens.

Aside from it not being clear where to position it in the top bar, I'm on board for that on small screens. Any thoughts on what to do on desktop resolutions?

any update on this? I'd like to use Furo, but we display a lot of jupyter notebooks that don't look good with the dark theme.

I think that this is still pending the design decision about where to put the toggle and what it should look like. If you wanted to help progress this, assuming that @pradyunsg would be happy with the change, you could implement the mechanism that would allow for the user to override the decision about theme colour made by prefers-color-scheme. That way, until the decision about what it should look like in the theme has been made, users would have the flexibility to implement their own toggle.

adrn commented

Just adding a +1 to this feature request -- I would love to have this option!

+1 would love this feature :)

If you want to see a feature implemented then it's best to give the issue a thumbs up, instead of leaving a comment, so that everyone watching the issue doesn't get a notification (See https://github.blog/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/).

j0yu commented

There's also GoogleChromeLabs/dark-mode-toggle which might be worth looking into too, which can remembers per-user settings across the site and is fairly customisable.

It's is currently used on Google's https://v8.dev/ at the very bottom (see #proudly-used-on section for screenshots of comparison)

Edit: Made my own proof of concept which is fairly rough

As prior art, Material for MkDocs supports three modes, a light, a dark, and a user preference.

Material for MkDocs supports two color schemes: a light mode, which is just called default, and a dark mode, which is called slate. The color scheme can be set via mkdocs.yml

The color scheme can also be set based on user preference, which makes use of the prefers-color-scheme media query, by setting the value in mkdocs.yml to preference

And then their Insiders version also supports an additional toggle switch.

You can see this in action here: https://fastapi.tiangolo.com/

Thanks for sharing those links here!

At the cost of sounding a bit smug, I've seen them before I wrote this theme or within a week of them being publicly announced. They're definitely useful but knowledge about them isn't the blocker here. :)

The blockers to implementing this are:

  1. Figuring out how to handle this in the SCSS (and html_theme_options overrides)
  2. Figuring out where the toggle should be (as I've mentioned in #24 (comment))
  3. Figuring out how to degrade gracefully when JS is disabled.

I don't know the answer to any of these, and haven't been super motivated to make time to explore them either. I think the best way to help move this forward would be to help figure out an answer to these questions. :)

Hi guys, I have built a sample using pure HTML, SCSS, JS and Jinja. It also supports the html_theme_options overrides for the themes as well as colors

Basically I created 2 top level CSS classes (dark and light) and separated the color scheme related CSS into those classes (thanks to @j0yu's work, it was easy for me to locate all the color scheme specific CSS). Also loaded the relevant pygment CSS for each theme under the respective top level class.

Then created a small JS function to assign the right class to the <html> tag on page load and a function to toggle the class on button press. The theme value is also stored in localStorage to remember the user's color scheme choice across reloads.

I have put a basic HTML button for toggling the color scheme in the left sidebar just above the search box for the time being. The toggle button is hidden using display: none when the author has fixed the color scheme from html_theme_options. Have used only vanilla JS, so should work across most browsers.

A demo is available on https://sdabhi23.github.io/furo/ and the code is available on https://github.com/sdabhi23/furo. Do share your thoughts about this approach @pradyunsg!

Can create a PR for this basic skeleton if the approach sounds good. More work needs to be done on thorough testing of all the functionalities and styling of the toggle button IMO.

Screen.Recording.2021-07-25.at.15.29.32.mov

This is now implemented, as a 3-state "toggle" between auto / dark / light. It only took refactoring a substantial portion of the colors-related styles in this theme, changing how CSS variables are handled in this theme, some duplication of the dark mode styles and completely working around how Sphinx generates pygments.css file by overwriting it with a custom variant of that file.

The overrides are JS-dependent. If you don't have JS enabled, you won't get the ability to override the colours.

I don't want to be adding a "force light mode" or anything like that -- there are only-dark and only-light classes that you can put on the elements to help with implementing elements that don't properly support both modes. I want documentation authors to support both of them if they're using Furo.

I'll cut a release next weekend. If you want to try it out, the current http://pradyunsg.me/furo/ pages reflect the current implementation that is on the main branch.

Thanks to @sdabhi23 for his sample above! It definitely saved me a lot of searching-for-the-right-syntax, even though I've made a few different choices on how things should work. ^>^

This is released in beta39. Thanks @pavithraes for the filing this!