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

Update mkdocs theme to bootstrap 5.3 and add support for dark mode. #3493

Merged
merged 3 commits into from Apr 12, 2024

Conversation

waylan
Copy link
Member

@waylan waylan commented Dec 1, 2023

This is related to #2248 but does not resolve that issue. That issue is requesting the option for the reader to select dark/light from the website itself. However, this only implements the option to select light/dark mode at build time from within the config file. Presumably, #2248 could be built on top of this.

As of version 5.3, Bootstrap supports color modes and provides light and dark modes out-of-the-box. The mkdocs theme has always used the Bootswatch Cerulean theme. Therefore, this updates the CSS and JS to version 5.3 of Bootstrap/Bootswatch and also updates most of the color definitions in the local CSS (base.css and extera.css) to use bootstrap variables (for example, admonitions now use Bootstrap colors). That way, switching between light and dark modes provides consistent results.

The challenge is with code blocks and the default syntax highlighter used by the theme (Highlight.js. Highlight.js defines isn't own background colors for code blocks in its CSS files. And Highlight.js provides 496 themes, not all of which have light/dark counterparts. This presents multiple challenges.

First of all, the background colors do not exactly match Bootstrap's colors. However, so long as every code block is processed by Highlight.js, then they all look the same. That means the nohighlight code blocks will get a different background color. Therefore, text should be used as the 'language' to maintain consistently styled code blocks (I have included an update to the docs in this regard).

At some point in the past, the hljs_style config option was added to the mkdocs theme. This option accepts the string name of any of Highlight.js' many themes and the template simply inserts that string into the URL pointing to the CSS file hosted in a CDN. In fact, this is why the theme uses a CDN. Otherwise, all 496 CSS files would need to be included with the theme files on MkDocs. We could pick two Highlight.js themes (one each for light and dark modes) and host them locally, but that would be a breaking change. Therefore, whenever the color mode is changed, the theme needs to be changed to match. There are a few different ways we could do this:

  1. Require the user to change both the color_mode and hljs_style independently. One would have no effect on the other.
  2. Provide a second "dark" config option (i.e.: hljs_style_dark) which defines the corresponding dark theme for Highlight.js. Then the relevant option could be used depending on color_mode.
  3. We could abandon Highlight.js and instead rely on the codehilite Markdown extension, which would require hosting our own CSS styles.
  4. Something else I haven't considered...

While option 1 would be the simplest, is would likely result in many complaints from users as the two config options would presumably be connected. Therefore, I have implemented option 2 here. Option 3 would be a breaking change, but would be much easier to work with in any future implementation of #2248.

Any input would be appreciated on the above issues.

Finally, I will note that as of Bootstrap version 5, jQuery was dropped as a dependency. Bootstrap now uses plain Javascript with the exception of Popper.js (which is included in the Bootstrap bundle) for popups/modals/etc. However, most of the Javascript in the mkdocs theme still uses jQuery. Presumably we could refactor all of the code in base.js to not depend on jQuery, which would have the protentional to reduce load times, etc. That said, many users likely have custom JavaScript of their own (in extra.js`) which expects jQuery, so removing jQuery completely would be a breaking change. Therefore, I have left that for a separate use to deal with. The only changes I made to the Javascript code were to update calls to Bootstrap's API.

@waylan
Copy link
Member Author

waylan commented Dec 1, 2023

I will update the failing test later. I am out of time today.

@waylan waylan marked this pull request as draft December 1, 2023 16:57
@waylan
Copy link
Member Author

waylan commented Dec 5, 2023

See #3189 which suggests a refactor of the Highlight.js config options.

@redtide
Copy link

redtide commented Dec 14, 2023

However, this only implements the option to select light/dark mode at build time from within the config file.

Most websites I visited and also some desktops give the possibility to choose dark/light versions of a theme at runtime, I don't see why to set it at build time instead making a dark version of the existing themes and choose if to use the system/dark/light color mode at runtime like the former do.
Other than that, if it's possible to use js (I was told it's possible via css but I wasn't able to make it work) you can also swap highlightjs at runtime (I used MKDocs to build this site).

@redtide
Copy link

redtide commented Dec 14, 2023

  1. Require the user to change both the color_mode and hljs_style independently. One would have no effect on the other.

I think the user should choose the hljs style in the config and the color mode at runtime (e.g. via dropdown "Light/Dark/Auto" menu).
The hljs theme might be only light or dark, so swapping will do nothing, otherwise work as expected, so yes, make hljs depending on color mode if both are set, mkdocs should not care if they match with the site theme.

  1. Provide a second "dark" config option (i.e.: hljs_style_dark) which defines the corresponding dark theme for Highlight.js. Then the relevant option could be used depending on color_mode.

Which IMO is the better option (see also below).

3 We could abandon Highlight.js and instead rely on the codehilite Markdown extension, which would require hosting our own CSS styles.

Personally I dislike this, but it's just my own opinion.

Finally, I will note that as of Bootstrap version 5, jQuery was dropped as a dependency. Bootstrap now uses plain Javascript with the exception of Popper.js

IIRC popper.js is needed for the search and keyboard dialogs (I had troubles with them when making the test theme I linked above because of missing popper.js/jquery), so maybe jquery could be made optional if not using them?

See #3189 which suggests a refactor of the Highlight.js config options.

That was a suggestion on how I did it, more or less, in my own theme but I guess it's not necessary a refactor if your hljs_style_dark addition idea would do the job without breaking compatibility.

@waylan
Copy link
Member Author

waylan commented Dec 14, 2023

However, this only implements the option to select light/dark mode at build time from within the config file.

Most websites I visited and also some desktops give the possibility to choose dark/light versions of a theme at runtime, I don't see why to set it at build time instead making a dark version of the existing themes and choose if to use the system/dark/light color mode at runtime like the former do.

Well, we have to start with something. Do we start with light as the default or dark? Different users may have different opinions about that. So we are giving them the option to choose. But once that is complete, then we can add the JS to do the in-browser switching. So its not like I'm wasting my time implementing a build-time config option. It will need to exist anyway. The in-browser switch is simply an additional add-on which can be added later.

I think the user should choose the hljs style in the config and the color mode at runtime (e.g. via dropdown "Light/Dark/Auto" menu).
The hljs theme might be only light or dark, so swapping will do nothing, otherwise work as expected, so yes, make hljs depending on color mode if both are set, mkdocs should not care if they match with the site theme.

I considered that. But then I tried it and wow is it hideous. Leaving the two unconnected would be a disservice to our users IMO.

See #3189 which suggests a refactor of the Highlight.js config options.

That was a suggestion on how I did it, more or less, in my own theme but I guess it's not necessary a refactor if your hljs_style_dark addition idea would do the job without breaking compatibility.

Personally, I actually prefer your suggestion in #3189. However, it breaks compatibility. Ideally, when a user upgrades to a new version of MkDocs, they should not need to make edits to their site config before building the first time. Sure, they may want to make edits to take advantage of new features, but their site should generally render the same without any edits. Of course, at times that is unavoidable, but we want to be cautious about when we choose to do so.

3 We could abandon Highlight.js and instead rely on the codehilite Markdown extension, which would require hosting our own CSS styles.

Personally I dislike this, but it's just my own opinion.

What is it that you dislike? Hosting our own CSS? The specific styles provided by Pygments? The lack of ability to chose from multiple options?

@redtide
Copy link

redtide commented Dec 14, 2023

Well, we have to start with something. Do we start with light as the default or dark? Different users may have different opinions about that. So we are giving them the option to choose. But once that is complete, then we can add the JS to do the in-browser switching. So its not like I'm wasting my time implementing a build-time config option. It will need to exist anyway. The in-browser switch is simply an additional add-on which can be added later.

I would say OK for light, you can check how it works on my test page link. If you support a system theme preference it will switch automatically so who cares about the default?
Sites around (and so desktops) have light theme as default AFAICS.

FTR: at some point I found the original "bootstrap4-test-page" project based on Jekyll, so I wanted to make one that worked with bootstrap5 to upgrade my sites, but being in the process to switch to MKDocs I wanted to make it as starting point for a "mkdocs-bootstrap-material" theme, so I hope it will be helpful for you in this context. OTOH it's just about implementing the bootstrap5 components and their default implementation as described in their docs, not much to be done differently. The in browser switch is the same, though IDK if the license is compatible (CC-BY-SA).

IMO the browser theme switch is fundamental, so you don't need to set anything in config, other than eventually a custom css for both light and dark and the HLJS ones.

I considered that. But then I tried it and wow is it hideous. Leaving the two unconnected would be a disservice to our users IMO.

Is that terrible in the link I posted? Again, I don't think MKDocs should care about the style an user sets. HLJS provides a lot, and you can't match all of them, so can't you just make your own css and let the user eventually override it?
I'm not sure what you mean with unconnected, if to switch both the site theme with the HLJS together is the same thing I prefer, if unconnected in the sense because not same colors that IDK what you can do about it, make a "MKDocs style" for both looks to me a waste of time to make it and also maintain it, users should choose what they like. As start I used a "GitHub dark palette" for mine, which seems to me working well with the HLJS GH versions.

Personally, I actually prefer your suggestion in #3189. However, it breaks compatibility. Ideally, when a user upgrades to a new version of MkDocs, they should not need to make edits to their site config before building the first time.

I haven't got this, can't you still support the old method and also add a new one (not great but I can't see a better option to avoid breakage), no?

What is it that you dislike? Hosting our own CSS? The specific styles provided by Pygments? The lack of ability to chose from multiple options?

Abandon HLJS and use codehilite. In general I like (and use) some of those extensions but there are some, like syntax highlight that I don't, but it's my opinion and by chance I started to use HLJS before trying to switch to MKDocs from Jekill, where previously I was using Google Prettify.

@waylan
Copy link
Member Author

waylan commented Dec 16, 2023

I added an auto mode, which follows the local system setting of the browser.

theme:
    name: mkdocs
    color_mode: auto

Color Mode switch

The trick was working out how to have both light and dark Highlight.js themes available for live switching (see 6485ff9). As I understand it, browsers do not download a disabled <link>, so no unnecessary resources are used with this solution.

One can also do either color_mode: light or color_mode: dark which builds with the one option only and does not do any switching (although, it could with a JavaScript call to setColorMode). Now it should be easy to add on-page switching.

@oprypin
Copy link
Contributor

oprypin commented Dec 16, 2023

Wow that's great stuff!

@redtide
Copy link

redtide commented Dec 16, 2023

Good job, looks great!
And by looking at commits and the preview I like the coding and visual styles!

@waylan
Copy link
Member Author

waylan commented Dec 20, 2023

I have now added a user option which is enabled with user_color_mode_toggle: true in the config.

Untitled

However, I needed to update fontawesome to version 6 as v3 did not have all of the appropriate icons. Personally, I would have likely used Bootstrap Icons, but I'm trying to maintain the existing dependencies for backward compatibility.

So now this one PR updates both bootstrap and fontawesome to the latest releases and adds a feature (color modes). I'm wondering if this is too much for one PR. If so, let me know and I'll break it up into a few.

Regardless, I still need to update the documentation.

@oprypin
Copy link
Contributor

oprypin commented Dec 20, 2023

This seems like the perfect opportunity to upgrade fontawesome. But yes, if we intend to squash this pull request into one, that would be too much. It might be prudent to switch the approach for this pull request to developing 1 ready stack of commits to be merged without squashing. Then a few other changes such as "Add user_color_mode_toggle" could also get their own commit. Anyway just seems much easier than multiple pull requests. Also I'm not sure when we'll actually get to merging and releasing this; I certainly would want to merge the fontawesome change right before merging the theme change (which the "stacked commits" approach would solve perfectly).

@redtide
Copy link

redtide commented Dec 20, 2023

This seems like the perfect opportunity to upgrade fontawesome

Not sure if you know about forkawesome, might be another alternative in case?

@waylan
Copy link
Member Author

waylan commented Dec 22, 2023

I believe this is ready to go. I have refactored the commits into 4 separate logical commits, which should be able to be committed as-is (not squashed). The last commit resolves #2248. See the commit messages and documentation updates for details.

@waylan waylan requested a review from oprypin December 22, 2023 14:28
Copy link
Contributor

@oprypin oprypin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Publishing my comments for commit "Update mkdocs theme to Bootstrap/Bootswatch 5.3.2"

All my edits are available as a commit 17168b9

Sorry for big delay :(

docs/css/extra.css Outdated Show resolved Hide resolved
mkdocs/themes/mkdocs/base.html Outdated Show resolved Hide resolved
mkdocs/themes/mkdocs/css/base.css Outdated Show resolved Hide resolved
mkdocs/themes/mkdocs/css/base.css Outdated Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we shouldn't add the map file because it refers to a file "dist/cerulean/bootstrap.css" which does not exist so is not usable

mkdocs/themes/mkdocs/css/base.css Outdated Show resolved Hide resolved
mkdocs/themes/mkdocs/css/base.css Outdated Show resolved Hide resolved
mkdocs/themes/mkdocs/css/base.css Outdated Show resolved Hide resolved
mkdocs/themes/mkdocs/css/base.css Show resolved Hide resolved
docs/css/extra.css Show resolved Hide resolved
Copy link
Contributor

@oprypin oprypin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Publishing comments for all color mode selector changes

Final state available in commit cf13620

If you want to be able to apply it directly, the 'dark mode' and 'user_color_mode_toggle' commits would have to be squashed first. Otherwise you have to recreate and apply my comments manually

mkdocs/themes/mkdocs/js/base.js Outdated Show resolved Hide resolved
mkdocs/themes/mkdocs/js/base.js Outdated Show resolved Hide resolved
mkdocs/themes/mkdocs/js/base.js Outdated Show resolved Hide resolved
mkdocs/themes/mkdocs/js/base.js Outdated Show resolved Hide resolved
mkdocs/themes/mkdocs/base.html Outdated Show resolved Hide resolved
mkdocs/themes/mkdocs/base.html Outdated Show resolved Hide resolved
mkdocs/themes/mkdocs/base.html Outdated Show resolved Hide resolved
mkdocs/themes/mkdocs/base.html Outdated Show resolved Hide resolved
@oprypin
Copy link
Contributor

oprypin commented Dec 30, 2023

Great stuff though. These are all the comments I have :)

@waylan
Copy link
Member Author

waylan commented Dec 31, 2023

Thanks for the feedback. I'll need to sort through it all when I have some time, which may be a while.

waylan and others added 3 commits March 16, 2024 15:16
Javascript has been updated to Bootstrap version 5.3.2 and CSS has been
updated to the the Bootswatch Cerulean theme version 5.3.2. Adding support
for a dark mode to the mkdocs theme is now possible.

All local colors (in base.css, extra.css, etc.) are now defined using
Bootstrap variables so that any future color modes (such as dark mode)
will be consistent.

Admonition styles have also been fully fleshed out with all colors being
Bootstrap colors (via variables) rather than our own custom colors.

Note that while Bootstrap version 5 dropped a dependency on jQuery, the
mkdocs theme is still making use of jQuery at this time. However, future
changes could remove the need for this dependency.

Co-authored-by: Oleh Prypin <oleh@pryp.in>
The font files have been moved from 'mkdocs/themes/mkdocs/fonts/' to
'mkdocs/themes/mkdocs/webfonts'. The 'brands', 'regular', and 'solid'
collections (all free collections) have been included as has the
'v4-font-face' shim for backward compatability.
Also add an optional toggle button for it.

Three new config options have been added:

1. 'color_mode' which can be set to one of 'light', 'dark', or 'auto'.
   Default is 'light' for backward compatability. The 'auto' color mode
   will check the system settings and automaticaly switch to light or
   dark mode on page load or when the system's color mode changes.
2. 'hljs_style_dark': the Highlight.js theme to use in 'dark_mode'.
   Default is 'github-dark' which matches the light mode default of
   'github'. The preexisting config option 'hljs_style' is used for
   'light' mode.
3. 'user_color_mode_toggle':
   Allow users to select their prefered color mode (light, dark, auto) from
   within the browser and save their preference for future page loads. The
   new config option 'user_color_mode_toggle' (default: 'False') can be
   enabled to display a toggle menu in the nav bar. The default value of the
   toggle menu on first load is the value set to 'color_mode'.

MkDocs' own documentation is now configured with 'color_mode: auto'.

Co-authored-by: Oleh Prypin <oleh@pryp.in>
@oprypin
Copy link
Contributor

oprypin commented Mar 16, 2024

I have made a new branch that is ready to be force-pushed to here. (Shall I just do that?) It contains all my suggested edits applied. Maybe it will be easier for you to just re-review it in the final shape, rather than checking my individual edits?

This is master...oprypin:mkdocs:themeup

  1. "Update mkdocs theme to Bootstrap/Bootswatch 5.3.2"
    • Before: b80b22b
    • After: 351b879
      (applied all my code suggestions, rebased without csslint)
  2. "Update FontAwesome to version 6"
  3. "Add support for a 'dark mode' to mkdocs theme" + "Add 'user_color_mode_toggle' to mkdocs theme"
    • Before: 7265192 + 02564cc
    • After: a836155
      (squashed 2 commits, rebased with updated markdownlint style, applied all my code suggestions)

@waylan
Copy link
Member Author

waylan commented Mar 18, 2024

If that is what you want to do. For the reasons stated in my individual responses, I actually think your changes are not improvements, but I don't have the time or energy to try to convince anyone of that. I also don't have the time to review your changes and likely won't for some months. So, you can merge your changes with this or just close this and open a new PR. Whatever works best for you.

@dagnelies
Copy link

This really looks great! Thanks for the effort you put into this. 👍
I also think that it should be merged ASAP because it's a great update, even if there are some details where your opinions diverge.
After all, many of such small details could still be updated later on . As long as it's "stable", it's all good! Happy Easter! 🥚 🐰 🥚

@oprypin oprypin added this to the 1.6.0 milestone Apr 10, 2024
@oprypin oprypin linked an issue Apr 10, 2024 that may be closed by this pull request
@oprypin
Copy link
Contributor

oprypin commented Apr 11, 2024

I plan to merge this for the 1.6.0 release with my edits, I hope that's OK.

I have checked the theme extensively for any deficiencies in Firefox/Linux, and I think any edits are for the better.

#3631

@oprypin oprypin merged commit 59a295f into mkdocs:master Apr 12, 2024
17 checks passed
@waylan waylan deleted the 2248 branch April 12, 2024 19:40
@Fryguy
Copy link

Fryguy commented Apr 12, 2024

I hadn't seen this work happening in the background after #2248 was closed, but this is awesome! Great work @waylan!

@squidfunk
Copy link
Sponsor Contributor

It's awesome to see dark mode coming to MkDocs' core themes! I checked the linked preview in #3631, and observed that the dark mode solution suffers from occasional white flashing, especially on very long pages (see attached video). I tried to find the code that implements dark mode to learn why, but to no avail, so my guess is that the selected preference is checked and applied "too late", i.e., at the end of the body. When there's a lot of content, the end of the parser sees the end of the body only after a while has passed, but the page already has partially rendered, which explains the flashing.

Ohne.Titel.mp4

The solution would be to move the code that decides what mode is to be applied to the beginning of body.

@squidfunk
Copy link
Sponsor Contributor

Working on #3649, I found some potential regressions:

  • The search modal's close button looks different
  • Search result titles are underlined
  • The table of contents collapse button on mobile looks different

Screenshots

Bildschirm­foto 2024-04-17 um 08 39 46 Bildschirm­foto 2024-04-17 um 08 39 18

@waylan
Copy link
Member Author

waylan commented Apr 17, 2024

There are a couple factors here. First, we updated to a more recent version of Bootstrap and Bootstrap changed the style of some items. The different look to the close and collapse buttons could be an intentional change on Bootstrap's part. That needs to be verified. The second factor is that we are not always using Bootstrap's defaults. IIRC links were changed in some way which caused our customizations to stop working. It could be that I missed the change to search results. In any event, this PR is already merged, seems like it would be appropriate to open a new issue to track this stuff. Also, unfortunately I do not have any time to work on this myself.

@oprypin
Copy link
Contributor

oprypin commented Apr 17, 2024

  • Yeah that close button does look really weird 🤔

  • All links are underlined, that's indeed changed

  • Yes the nav collapse button looks different, not sure what's up with that but it's not bad

Thanks for checking

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Dark mode support based on OS choice
6 participants