Remember chosen theme in localStorage

This way, the selected theme is kept when changing pages, and for subsequent visits. To prevent flickering, we set the selected theme in a blocking script directly on load. To speed things up further, we now use a `data-theme` attribute instead of classes on the body tag, this way we don't need to wait until the body element is loaded.
This commit is contained in:
Philipp Oppermann
2021-10-17 14:51:00 +02:00
parent 3281df3a41
commit 69917e234c
3 changed files with 44 additions and 39 deletions

View File

@@ -92,7 +92,7 @@ body {
@include set-colors-light(); @include set-colors-light();
} }
body.dark { [data-theme="dark"] body {
@include set-colors-dark(); @include set-colors-dark();
} }
@@ -103,7 +103,7 @@ body.dark {
@include set-colors-dark(); @include set-colors-dark();
} }
/* Override dark mode with light mode styles if the user decides to swap */ /* Override dark mode with light mode styles if the user decides to swap */
body.light { [data-theme="light"] body {
@include set-colors-light(); @include set-colors-light();
} }
} }
@@ -966,7 +966,7 @@ img {
.dark-mode-note { .dark-mode-note {
display: none; display: none;
} }
body.dark .dark-mode-note { [data-theme="dark"] .dark-mode-note {
display: block; display: block;
} }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
@@ -975,7 +975,7 @@ body.dark .dark-mode-note {
display: block; display: block;
} }
/* Override dark mode with light mode styles if the user decides to swap */ /* Override dark mode with light mode styles if the user decides to swap */
body.light .dark-mode-note { [data-theme="light"] .dark-mode-note {
display: none; display: none;
} }
} }
@@ -994,7 +994,7 @@ body.dark .dark-mode-note {
@include light-switch-light(); @include light-switch-light();
} }
body.dark .light-switch { [data-theme="dark"] .light-switch {
@include light-switch-dark(); @include light-switch-dark();
} }
@@ -1003,7 +1003,7 @@ body.dark .light-switch {
@include light-switch-dark(); @include light-switch-dark();
} }
body.light .light-switch { [data-theme="light"] .light-switch {
@include light-switch-light(); @include light-switch-light();
} }
} }

View File

@@ -1,17 +1,21 @@
window.onload = function() { window.onload = function () {
var container = document.querySelector('#toc-aside'); let theme = localStorage.getItem("theme");
if (theme != null) {
set_theme(theme)
}
let container = document.querySelector('#toc-aside');
if (container != null) { if (container != null) {
resize_toc(container); resize_toc(container);
toc_scroll_position(container); toc_scroll_position(container);
window.onscroll = function() { toc_scroll_position(container) }; window.onscroll = function () { toc_scroll_position(container) };
} }
} }
function resize_toc(container) { function resize_toc(container) {
var containerHeight = container.clientHeight; let containerHeight = container.clientHeight;
var resize = function() { let resize = function () {
if (containerHeight > document.documentElement.clientHeight - 100) { if (containerHeight > document.documentElement.clientHeight - 100) {
container.classList.add('coarse'); container.classList.add('coarse');
} else { } else {
@@ -20,8 +24,8 @@ function resize_toc(container) {
}; };
resize(); resize();
var resizeId; let resizeId;
window.onresize = function() { window.onresize = function () {
clearTimeout(resizeId); clearTimeout(resizeId);
resizeId = setTimeout(resize, 300); resizeId = setTimeout(resize, 300);
}; };
@@ -32,7 +36,6 @@ function toc_scroll_position(container) {
// skip computation if ToC is not visible // skip computation if ToC is not visible
return; return;
} }
var items = container.querySelectorAll("li")
// remove active class for all items // remove active class for all items
for (item of container.querySelectorAll("li")) { for (item of container.querySelectorAll("li")) {
@@ -40,15 +43,15 @@ function toc_scroll_position(container) {
} }
// look for active item // look for active item
var site_offset = document.documentElement.scrollTop; let site_offset = document.documentElement.scrollTop;
var current_toc_item = null; let current_toc_item = null;
for (item of container.querySelectorAll("li")) { for (item of container.querySelectorAll("li")) {
if (item.offsetParent === null) { if (item.offsetParent === null) {
// skip items that are not visible // skip items that are not visible
continue; continue;
} }
var anchor = item.firstElementChild.getAttribute("href"); let anchor = item.firstElementChild.getAttribute("href");
var heading = document.querySelector(anchor); let heading = document.querySelector(anchor);
if (heading.offsetTop <= (site_offset + document.documentElement.clientHeight / 3)) { if (heading.offsetTop <= (site_offset + document.documentElement.clientHeight / 3)) {
current_toc_item = item; current_toc_item = item;
} else { } else {
@@ -63,25 +66,20 @@ function toc_scroll_position(container) {
} }
function toggle_lights() { function toggle_lights() {
var body = document.querySelector("body"); if (document.documentElement.getAttribute("data-theme") === "dark") {
var comment_form = document.querySelector("iframe.giscus-frame"); set_theme("light")
if (body != null) { } else {
if (body.classList.contains("dark")) { set_theme("dark")
body.classList.replace("dark", "light");
if (comment_form != null) {
comment_form.contentWindow.postMessage({
giscus: { setConfig: { theme: 'light' } }
}, "https://giscus.app")
}
} else {
body.classList.remove("light");
body.classList.add("dark");
if (comment_form != null) {
comment_form.contentWindow.postMessage({
giscus: { setConfig: { theme: 'dark' } }
}, "https://giscus.app")
}
}
console.log(body)
} }
} }
function set_theme(theme) {
let comment_form = document.querySelector("iframe.giscus-frame");
document.documentElement.setAttribute("data-theme", theme);
if (comment_form != null) {
comment_form.contentWindow.postMessage({
giscus: { setConfig: { theme: theme } }
}, "https://giscus.app")
}
localStorage.setItem("theme", theme);
}

View File

@@ -17,6 +17,13 @@
<link rel="alternate" type="application/rss+xml" title="RSS feed for os.phil-opp.com" href="{{ config.base_url | safe }}/rss.xml" /> <link rel="alternate" type="application/rss+xml" title="RSS feed for os.phil-opp.com" href="{{ config.base_url | safe }}/rss.xml" />
<script>
let theme = localStorage.getItem("theme");
if (theme != null) {
document.documentElement.setAttribute("data-theme", theme);
}
</script>
<script async src="/js/edition-2/main.js"></script> <script async src="/js/edition-2/main.js"></script>
<title>{% block title %}{% endblock title %}</title> <title>{% block title %}{% endblock title %}</title>