rstudio / distill

Distill for R Markdown
https://rstudio.github.io/distill/
Apache License 2.0
422 stars 57 forks source link

Option to toggle dark/light themes #272

Open shamindras opened 3 years ago

shamindras commented 3 years ago

I'm currently enjoying using the latest version of distill i.e. distill_1.1. Thanks for making it.

I particularly liked the ease in which themes can now be changed. I was wondering if it is possible to have an icon to flip between dark/light versions of themes? I've seen this quite commonly in the Hugo Academic Theme in some blogs of R users.

For distill, I presume this would require the user to create theme-dark.css and theme-light.css, but I'm unsure if it would be possible to have a toggle button for this within distill.

I thought to ask if it is easy to roll this within the existing distill setup, or if there are any plans to introduce this useful functionality?

Note: I'm currently using the break to update my distill blog, so flagging a few issues that naturally arise when I'm testing out the new distill package. I will keep these to a minimum, since I appreciate how much work goes into making this package 👍 .

jjallaire commented 3 years ago

No, there isn't a straightforward way to define light and dark themes (other than what you mentioned having two different theme css files and statically binding to one at render time). You could probably rig something up w/ JavaScript to do what you are hoping for but it might get pretty involved.

shamindras commented 3 years ago

Thanks @jjallaire ! I figured this would be the case. Please feel free to close this issue.

Although I'm hoping a distill user more familiar with JS will see this issue and consider providing a good solution to this 😄 .

Felixmil commented 3 years ago

I would love to have this feature also ! Maybe this can help the future more familiar with JS distill user: Juba who is maintaining {rmdformats} implemented this in its downcute theme 👀

jmbuhr commented 3 years ago

I have a partial solution, maybe someone has an idea for fixing the current problem. Here are the steps:

Setup

In _site.yaml include

navbar:
  right:
    - icon: fas fa-adjust
      href: "javascript:switchTheme();"
output:
  distill::distill_article:
    theme: theme.css
    includes:
      in_header: "_header.html"

where _header.html in the root directory is:

<link disabled rel='stylesheet' href='darkmode.css' id="dark-mode-css">

<script>
  let theme = localStorage.getItem("theme");
  if (!theme) {
    if (window.matchMedia("(prefers-color-scheme: dark)").matches ) {
      theme = "dark";
    } else {
      theme = "light";
    }
  }
  setTheme();

  function switchTheme() {
    if (theme === "light") {
      theme = "dark";
    } else {
      theme = "light";
    }
    localStorage.setItem("theme", theme);
    setTheme();
  }

  function setTheme() {
    if (theme === "dark") {
      document.getElementById("dark-mode-css").disabled = true;
    } else {
      document.getElementById("dark-mode-css").disabled = false;
    }
  }
</script>

darkmode.css in the root directory can look something like:

body {
  background-color: #252729;
}

img {
  opacity: .75;
  transition: opacity .5s ease-in-out;
}

img:hover {
  opacity: 1;
}

html {
  --title-color:     #b1bcc8;
  --header-color:    #b1bcc8;
  --body-color:      #b1bcc8;
  --aside-color:     #b1bcc8;
  --fig-cap-color:   #b1bcc8;
}

d-article {
  color: #b1bcc8;
}

.distill-site-footer {
  --text-color: #b1bcc8;
  --bkgd-color: #252729;
}

d-byline {
  --heading-color: #b1bcc8;
  --body-color: #b1bcc8;
}

d-appendix {
  --heading-color: #b1bcc8;
  --text-color: #b1bcc8;
}

d-appendix a {
  color: rgb(83 255 35 / 60%);
}

Problem

This setup works for all the toplevel pages like index and listing pages but fails when opening individual posts. The reason for this is that when the posts are copied to the publish / docs directory, the links in the navbar are replaced. Meaning e.g. href: posts.html in _site.yaml becomes ../../posts.html when viewed from an article in the posts directory. The same happens to javascript:switchTheme();, so the browser tries to find it as a link. Meanwhile, the link to darkmode.css has the opposite problem. It is not updated so the browser searches for it in the posts directory (relative to the article) instead of the root directory.

jmbuhr commented 3 years ago

For those still interested, I coded a js solution to toggle a darkmode. It starts in the users prefered colorscheme and is toggle-able via a button. The choice is remembered in local storage. The css is still a little rough around the edges, as there appear to be a bunch of edgecases, tags and classes in distill, but it works. This is my website and here is the repo for it with the commit that added the darkmode: https://github.com/jmbuhr/jmbuhr.github.io/tree/c5093a3b882b1542f48ee0bfbdf2ea788b3a773f

If you want to recreate this, what you need is: