Skip to content

Commit 2519dff

Browse files
committed
feat: add darkmode toggle
1 parent 35696bf commit 2519dff

File tree

102 files changed

+3453
-1810
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+3453
-1810
lines changed

src/html/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ const FUSE_FILENAME: &str = "fuse.js";
7272
const SEARCH_JS: &str = include_str!("./templates/pages/search.js");
7373
const SEARCH_FILENAME: &str = "search.js";
7474

75+
const DARKMODE_TOGGLE_JS: &str =
76+
include_str!("./templates/pages/darkmode_toggle.js");
77+
const DARKMODE_TOGGLE_FILENAME: &str = "darkmode_toggle.js";
78+
7579
fn setup_hbs() -> Result<Handlebars<'static>, anyhow::Error> {
7680
let mut reg = Handlebars::new();
7781
reg.register_escape_fn(|str| html_escape::encode_safe(str).into_owned());
@@ -227,6 +231,14 @@ fn setup_hbs() -> Result<Handlebars<'static>, anyhow::Error> {
227231
"icons/menu",
228232
include_str!("./templates/icons/menu.svg"),
229233
)?;
234+
reg.register_template_string(
235+
"icons/sun",
236+
include_str!("./templates/icons/sun.svg"),
237+
)?;
238+
reg.register_template_string(
239+
"icons/moon",
240+
include_str!("./templates/icons/moon.svg"),
241+
)?;
230242

231243
Ok(reg)
232244
}
@@ -1153,6 +1165,7 @@ pub fn generate(
11531165
files.insert(RESET_STYLESHEET_FILENAME.into(), RESET_STYLESHEET.into());
11541166
files.insert(FUSE_FILENAME.into(), FUSE_JS.into());
11551167
files.insert(SEARCH_FILENAME.into(), SEARCH_JS.into());
1168+
files.insert(DARKMODE_TOGGLE_FILENAME.into(), DARKMODE_TOGGLE_JS.into());
11561169
#[cfg(feature = "comrak")]
11571170
files.insert(
11581171
comrak::COMRAK_STYLESHEET_FILENAME.into(),

src/html/pages.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use std::borrow::Cow;
1515
use std::cmp::Ordering;
1616
use std::rc::Rc;
1717

18+
use super::DARKMODE_TOGGLE_FILENAME;
1819
use super::FUSE_FILENAME;
1920
use super::PAGE_STYLESHEET_FILENAME;
2021
use super::RESET_STYLESHEET_FILENAME;
@@ -39,7 +40,8 @@ pub struct HtmlHeadCtx {
3940
url_search_index: String,
4041
script_js: String,
4142
fuse_js: String,
42-
url_search: String,
43+
search_js: String,
44+
darkmode_toggle_js: String,
4345
head_inject: Option<String>,
4446
disable_search: bool,
4547
}
@@ -73,7 +75,8 @@ impl HtmlHeadCtx {
7375
url_search_index: format!("{root}{SEARCH_INDEX_FILENAME}"),
7476
script_js: format!("{root}{SCRIPT_FILENAME}"),
7577
fuse_js: format!("{root}{FUSE_FILENAME}"),
76-
url_search: format!("{root}{SEARCH_FILENAME}"),
78+
search_js: format!("{root}{SEARCH_FILENAME}"),
79+
darkmode_toggle_js: format!("{root}{DARKMODE_TOGGLE_FILENAME}"),
7780
head_inject: ctx.head_inject.clone().map(|head_inject| head_inject(root)),
7881
disable_search: ctx.disable_search,
7982
}

src/html/templates/comrak.gen.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/html/templates/icons/moon.svg

Lines changed: 4 additions & 0 deletions
Loading

src/html/templates/icons/sun.svg

Lines changed: 12 additions & 0 deletions
Loading
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
function setTheme(theme, themeToggle) {
2+
if (theme === "dark") {
3+
document.documentElement.classList.add("dark");
4+
localStorage.setItem("theme", "dark");
5+
} else {
6+
document.documentElement.classList.remove("dark");
7+
localStorage.setItem("theme", "light");
8+
}
9+
10+
const darkIcon = themeToggle.children[0];
11+
const lightIcon = themeToggle.children[1];
12+
13+
if (theme === "dark") {
14+
darkIcon.classList.add("hidden");
15+
lightIcon.classList.remove("hidden");
16+
} else {
17+
darkIcon.classList.remove("hidden");
18+
lightIcon.classList.add("hidden");
19+
}
20+
}
21+
22+
window.addEventListener("load", () => {
23+
const themeToggle = document.getElementById("theme-toggle");
24+
25+
const storedTheme = localStorage.getItem("theme");
26+
const systemPrefersDark =
27+
window.matchMedia("(prefers-color-scheme: dark)").matches;
28+
29+
if (storedTheme) {
30+
setTheme(storedTheme, themeToggle);
31+
} else {
32+
setTheme(systemPrefersDark ? "dark" : "light", themeToggle);
33+
}
34+
35+
if (themeToggle) {
36+
themeToggle.addEventListener("click", () => {
37+
const isDark = document.documentElement.classList.contains("dark");
38+
setTheme(isDark ? "light" : "dark", themeToggle);
39+
});
40+
}
41+
});
42+
43+
// prevent flash
44+
const theme = localStorage.getItem("theme") ||
45+
(window.matchMedia("(prefers-color-scheme: dark)").matches
46+
? "dark"
47+
: "light");
48+
document.documentElement.classList.add(theme);

src/html/templates/pages/html_head.hbs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@
1010
<link id="ddocResetStylesheet" rel="stylesheet" href="{{reset_stylesheet_url}}">
1111
{{{~head_inject~}}}
1212

13+
<script src="{{script_js}}" defer></script>
14+
<script src="{{darkmode_toggle_js}}"></script>
15+
1316
{{~#if (not disable_search)~}}
1417
<script src="{{url_search_index}}" defer></script>
15-
<script src="{{script_js}}" defer></script>
1618
<script src="{{fuse_js}}" defer></script>
17-
<script src="{{url_search}}" defer></script>
19+
<script src="{{search_js}}" defer></script>
1820
{{~/if~}}
1921
</head>
2022
<body>

src/html/templates/pages/page.css

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,17 @@ body {
8282
}
8383
}
8484
}
85+
86+
#topnav {
87+
@apply top-0 sticky z-50 py-3 h-14 bg-white/10 dark:bg-backgroundDark/90
88+
dark:text-white/90 border-b border-gray-300 dark:border-gray-700;
89+
}
90+
91+
#theme-toggle {
92+
@apply text-gray-500 dark:text-gray-400 hover:bg-gray-100
93+
dark:hover:bg-gray-700 rounded p-1.5;
94+
95+
* {
96+
@apply size-5;
97+
}
98+
}

src/html/templates/pages/page.gen.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/html/templates/pages/tailwind.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { type Config } from "npm:tailwindcss@3.4.3";
22

33
export default {
4+
darkMode: "class",
45
theme: {
56
extend: {
67
colors: {

src/html/templates/pages/top_nav.hbs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
1-
<nav
2-
class="top-0 sticky z-50 py-3 h-14 bg-white/10 dark:bg-backgroundDark/90 dark:text-white/90 border-b border-gray-300 dark:border-gray-700"
3-
id="topnav">
1+
<nav id="topnav">
42
<div class="h-full">
5-
<div>
3+
<div class="flex items-center">
64
{{~> breadcrumbs breadcrumbs_ctx ~}}
75
</div>
86

9-
{{#if (not disable_search)}}
10-
<input
11-
type="text"
12-
id="searchbar"
13-
style="display: none;"
14-
class="py-2 px-2.5 mx-1 rounded text-sm border border-gray-300 bg-transparent dark:bg-gray-800 dark:border-gray-700"
15-
/>
16-
{{/if}}
7+
<div class="flex items-center gap-2">
8+
<button id="theme-toggle" type="button" aria-label="Toggle dark mode">
9+
{{~> icons/moon ~}}
10+
{{~> icons/sun class="hidden" ~}}
11+
</button>
12+
13+
{{#if (not disable_search)}}
14+
<input
15+
type="text"
16+
id="searchbar"
17+
style="display: none;"
18+
class="py-2 px-2.5 mx-1 rounded text-sm border border-gray-300 bg-transparent dark:bg-gray-800 dark:border-gray-700"
19+
/>
20+
{{/if}}
21+
</div>
1722
</div>
1823
</nav>

src/html/templates/styles.gen.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tailwind.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export default {
4141
"./src/html/**/*.rs",
4242
"./src/html/templates/*.hbs",
4343
],
44+
darkMode: "class",
4445
safelist: [
4546
{
4647
pattern: new RegExp(`^text-(${Object.keys(extraColors).join("|")})$`),

tests/html_test.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ async fn html_doc_dts() {
193193
"./~/WebSocket.html",
194194
"./~/WebSocket.prototype.html",
195195
"comrak.css",
196+
"darkmode_toggle.js",
196197
"fuse.js",
197198
"page.css",
198199
"reset.css",
@@ -247,6 +248,7 @@ async fn html_doc_files_single() {
247248
"./~/Foobar.html",
248249
"./~/Foobar.prototype.html",
249250
"comrak.css",
251+
"darkmode_toggle.js",
250252
"fuse.js",
251253
"page.css",
252254
"reset.css",
@@ -380,6 +382,7 @@ async fn html_doc_files_multiple() {
380382
"comrak.css",
381383
"d/index.html",
382384
"d/~/externalFunction.html",
385+
"darkmode_toggle.js",
383386
"foo/index.html",
384387
"foo/~/default.html",
385388
"foo/~/x.html",

tests/snapshots/html_test__html_doc_dts-10.snap

Lines changed: 48 additions & 11 deletions
Large diffs are not rendered by default.

tests/snapshots/html_test__html_doc_dts-11.snap

Lines changed: 11 additions & 35 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)