From 1eb4ecc4c066edb8124beb854ae9adab117ba891 Mon Sep 17 00:00:00 2001 From: Michael Hughes Date: Sat, 7 Mar 2026 14:44:20 -0700 Subject: [PATCH 1/2] feat: add dark mode support across website and homepage --- _layouts/layout.html | 16 ++ _layouts/website/layout.html | 1 + cn/_layouts/layout.html | 1 + cn/_layouts/website/header.html | 13 ++ cn/_layouts/website/page.html | 1 + de/_layouts/layout.html | 1 + de/_layouts/website/header.html | 13 ++ de/_layouts/website/page.html | 1 + en/_layouts/layout.html | 1 + en/_layouts/website/header.html | 13 ++ en/_layouts/website/page.html | 1 + es/_layouts/layout.html | 1 + es/_layouts/website/header.html | 13 ++ es/_layouts/website/page.html | 1 + fr/_layouts/layout.html | 1 + fr/_layouts/website/header.html | 13 ++ fr/_layouts/website/page.html | 1 + id/_layouts/layout.html | 1 + id/_layouts/website/header.html | 13 ++ id/_layouts/website/page.html | 1 + np/_layouts/layout.html | 1 + np/_layouts/website/header.html | 13 ++ np/_layouts/website/page.html | 1 + tr/_layouts/layout.html | 1 + tr/_layouts/website/header.html | 13 ++ tr/_layouts/website/page.html | 1 + website/copy-code.css | 18 ++ website/dark-mode.css | 292 ++++++++++++++++++++++++++++++++ website/dark-mode.js | 39 +++++ 29 files changed, 486 insertions(+) create mode 100644 website/dark-mode.css create mode 100644 website/dark-mode.js diff --git a/_layouts/layout.html b/_layouts/layout.html index a3a1586f..a0fc75f5 100644 --- a/_layouts/layout.html +++ b/_layouts/layout.html @@ -18,9 +18,25 @@ {% endfor %} {% endblock %} + {% block head %}{% endblock %} + {% block body %}{% endblock %} {% block javascript %}{% endblock %} diff --git a/_layouts/website/layout.html b/_layouts/website/layout.html index a299217f..5ab1b054 100644 --- a/_layouts/website/layout.html +++ b/_layouts/website/layout.html @@ -10,6 +10,7 @@ + {% endblock %} {% block style %} diff --git a/cn/_layouts/layout.html b/cn/_layouts/layout.html index a3a1586f..016bdecd 100644 --- a/cn/_layouts/layout.html +++ b/cn/_layouts/layout.html @@ -18,6 +18,7 @@ {% endfor %} {% endblock %} + {% block head %}{% endblock %} diff --git a/cn/_layouts/website/header.html b/cn/_layouts/website/header.html index 9f44acc8..dbbf0d63 100644 --- a/cn/_layouts/website/header.html +++ b/cn/_layouts/website/header.html @@ -9,5 +9,18 @@

{{ page.title }}

+ {% endblock %} \ No newline at end of file diff --git a/cn/_layouts/website/page.html b/cn/_layouts/website/page.html index 2c3b0b86..bf3f5db4 100644 --- a/cn/_layouts/website/page.html +++ b/cn/_layouts/website/page.html @@ -125,5 +125,6 @@ }); + {% endblock %} \ No newline at end of file diff --git a/de/_layouts/layout.html b/de/_layouts/layout.html index a3a1586f..016bdecd 100644 --- a/de/_layouts/layout.html +++ b/de/_layouts/layout.html @@ -18,6 +18,7 @@ {% endfor %} {% endblock %} + {% block head %}{% endblock %} diff --git a/de/_layouts/website/header.html b/de/_layouts/website/header.html index 9f44acc8..dbbf0d63 100644 --- a/de/_layouts/website/header.html +++ b/de/_layouts/website/header.html @@ -9,5 +9,18 @@

{{ page.title }}

+ {% endblock %} \ No newline at end of file diff --git a/de/_layouts/website/page.html b/de/_layouts/website/page.html index 2c3b0b86..bf3f5db4 100644 --- a/de/_layouts/website/page.html +++ b/de/_layouts/website/page.html @@ -125,5 +125,6 @@ }); + {% endblock %} \ No newline at end of file diff --git a/en/_layouts/layout.html b/en/_layouts/layout.html index a3a1586f..016bdecd 100644 --- a/en/_layouts/layout.html +++ b/en/_layouts/layout.html @@ -18,6 +18,7 @@ {% endfor %} {% endblock %} + {% block head %}{% endblock %} diff --git a/en/_layouts/website/header.html b/en/_layouts/website/header.html index 9f44acc8..dbbf0d63 100644 --- a/en/_layouts/website/header.html +++ b/en/_layouts/website/header.html @@ -9,5 +9,18 @@

{{ page.title }}

+ {% endblock %} \ No newline at end of file diff --git a/en/_layouts/website/page.html b/en/_layouts/website/page.html index 2c3b0b86..bf3f5db4 100644 --- a/en/_layouts/website/page.html +++ b/en/_layouts/website/page.html @@ -125,5 +125,6 @@ }); + {% endblock %} \ No newline at end of file diff --git a/es/_layouts/layout.html b/es/_layouts/layout.html index a3a1586f..016bdecd 100644 --- a/es/_layouts/layout.html +++ b/es/_layouts/layout.html @@ -18,6 +18,7 @@ {% endfor %} {% endblock %} + {% block head %}{% endblock %} diff --git a/es/_layouts/website/header.html b/es/_layouts/website/header.html index 9f44acc8..dbbf0d63 100644 --- a/es/_layouts/website/header.html +++ b/es/_layouts/website/header.html @@ -9,5 +9,18 @@

{{ page.title }}

+ {% endblock %} \ No newline at end of file diff --git a/es/_layouts/website/page.html b/es/_layouts/website/page.html index 2c3b0b86..bf3f5db4 100644 --- a/es/_layouts/website/page.html +++ b/es/_layouts/website/page.html @@ -125,5 +125,6 @@ }); + {% endblock %} \ No newline at end of file diff --git a/fr/_layouts/layout.html b/fr/_layouts/layout.html index a3a1586f..016bdecd 100644 --- a/fr/_layouts/layout.html +++ b/fr/_layouts/layout.html @@ -18,6 +18,7 @@ {% endfor %} {% endblock %} + {% block head %}{% endblock %} diff --git a/fr/_layouts/website/header.html b/fr/_layouts/website/header.html index 9f44acc8..dbbf0d63 100644 --- a/fr/_layouts/website/header.html +++ b/fr/_layouts/website/header.html @@ -9,5 +9,18 @@

{{ page.title }}

+ {% endblock %} \ No newline at end of file diff --git a/fr/_layouts/website/page.html b/fr/_layouts/website/page.html index 2c3b0b86..bf3f5db4 100644 --- a/fr/_layouts/website/page.html +++ b/fr/_layouts/website/page.html @@ -125,5 +125,6 @@ }); + {% endblock %} \ No newline at end of file diff --git a/id/_layouts/layout.html b/id/_layouts/layout.html index a3a1586f..016bdecd 100644 --- a/id/_layouts/layout.html +++ b/id/_layouts/layout.html @@ -18,6 +18,7 @@ {% endfor %} {% endblock %} + {% block head %}{% endblock %} diff --git a/id/_layouts/website/header.html b/id/_layouts/website/header.html index 9f44acc8..dbbf0d63 100644 --- a/id/_layouts/website/header.html +++ b/id/_layouts/website/header.html @@ -9,5 +9,18 @@

{{ page.title }}

+ {% endblock %} \ No newline at end of file diff --git a/id/_layouts/website/page.html b/id/_layouts/website/page.html index 2c3b0b86..bf3f5db4 100644 --- a/id/_layouts/website/page.html +++ b/id/_layouts/website/page.html @@ -125,5 +125,6 @@ }); + {% endblock %} \ No newline at end of file diff --git a/np/_layouts/layout.html b/np/_layouts/layout.html index a3a1586f..016bdecd 100644 --- a/np/_layouts/layout.html +++ b/np/_layouts/layout.html @@ -18,6 +18,7 @@ {% endfor %} {% endblock %} + {% block head %}{% endblock %} diff --git a/np/_layouts/website/header.html b/np/_layouts/website/header.html index 9f44acc8..dbbf0d63 100644 --- a/np/_layouts/website/header.html +++ b/np/_layouts/website/header.html @@ -9,5 +9,18 @@

{{ page.title }}

+ {% endblock %} \ No newline at end of file diff --git a/np/_layouts/website/page.html b/np/_layouts/website/page.html index 2c3b0b86..bf3f5db4 100644 --- a/np/_layouts/website/page.html +++ b/np/_layouts/website/page.html @@ -125,5 +125,6 @@ }); + {% endblock %} \ No newline at end of file diff --git a/tr/_layouts/layout.html b/tr/_layouts/layout.html index a3a1586f..016bdecd 100644 --- a/tr/_layouts/layout.html +++ b/tr/_layouts/layout.html @@ -18,6 +18,7 @@ {% endfor %} {% endblock %} + {% block head %}{% endblock %} diff --git a/tr/_layouts/website/header.html b/tr/_layouts/website/header.html index 9f44acc8..dbbf0d63 100644 --- a/tr/_layouts/website/header.html +++ b/tr/_layouts/website/header.html @@ -9,5 +9,18 @@

{{ page.title }}

+ {% endblock %} \ No newline at end of file diff --git a/tr/_layouts/website/page.html b/tr/_layouts/website/page.html index 2c3b0b86..bf3f5db4 100644 --- a/tr/_layouts/website/page.html +++ b/tr/_layouts/website/page.html @@ -125,5 +125,6 @@ }); + {% endblock %} \ No newline at end of file diff --git a/website/copy-code.css b/website/copy-code.css index c5f27b8f..ac20d086 100644 --- a/website/copy-code.css +++ b/website/copy-code.css @@ -38,4 +38,22 @@ .code-wrapper pre { margin-top: 0 !important; padding-right: 42px !important; +} + +html.dark-mode .copy-code-button { + background-color: rgba(255, 255, 255, 0.06); + border-color: rgba(255, 255, 255, 0.08); + color: #9daab6; + opacity: 0.9; + backdrop-filter: blur(2px); +} + +html.dark-mode .copy-code-button:hover { + background-color: rgba(255, 255, 255, 0.1); + border-color: rgba(255, 255, 255, 0.14); + color: #d7e2ea; +} + +html.dark-mode .copy-code-button.success { + color: #7ee787; } \ No newline at end of file diff --git a/website/dark-mode.css b/website/dark-mode.css new file mode 100644 index 00000000..df9ce60d --- /dev/null +++ b/website/dark-mode.css @@ -0,0 +1,292 @@ +/* Default Light Theme */ +:root { + --bg-color: #ffffff; + --text-color: #333333; + --code-bg: #f7f7f7; + --sidebar-bg: #f5f7f9; + + /* Content semantics */ + --muted-text: #666666; + --border-color: #dddddd; + --hr-color: #e7e7e7; + --link-color: #4183c4; + + /* Tables */ + --table-row-bg: #ffffff; + --table-row-alt-bg: #f8f8f8; + --table-header-bg: #ffffff; + + /* Exercises (match gitbook-plugin-exercises light defaults) */ + --exercise-bg: #ffffff; + --exercise-text: #333333; + --exercise-border: #2f8cde; + --exercise-header-bg: #2f8cde; + --exercise-header-text: #ffffff; + --exercise-editor-bg: #ffffff; + --exercise-editor-border: #dddddd; +} + +/* Dark Theme Overrides */ +.dark-mode { + --bg-color: #1a1a1b; + --text-color: #9DAAB6; + --code-bg: #2d2d2d; + --sidebar-bg: #121213; + + /* Content semantics */ + --muted-text: #7f8b96; + --border-color: #2f3336; + --hr-color: #2b2f33; + --link-color: #7ab7ff; + + /* Tables */ + --table-row-bg: #1f2124; + --table-row-alt-bg: #1b1d20; + --table-header-bg: #23262a; + + /* Exercises (dark mode) */ + --exercise-bg: #161718; + --exercise-text: var(--text-color); + --exercise-border: #2f8cde; + --exercise-header-bg: #2f8cde; + --exercise-header-text: #ffffff; + --exercise-editor-bg: #121213; + --exercise-editor-border: var(--border-color); +} + +body .book-summary ul.summary li a, +body .book-body .markdown-section { + background-color: var(--bg-color); + color: var(--text-color); + transition: background-color 0.3s, color 0.3s; +} + +.page-wrapper { + background-color: var(--bg-color); +} + +.book-header { + background-color: var(--sidebar-bg); + color: var(--text-color); + display: flex; + align-items: center; + gap: 12px; +} + +.book-summary ul.summary li.active > a { + background-color: var(--sidebar-bg); +} + +.book-summary ul.summary li { + background-color: var(--sidebar-bg); +} + +.book.with-summary .book-summary { + background-color: var(--sidebar-bg); +} + +.book-body .body-inner { + background-color: var(--bg-color); +} + +/* Exercises (fix unfinished look + restore light mode appearance) */ +.book .book-body .page-wrapper .page-inner .exercise { + background-color: var(--exercise-bg); + color: var(--exercise-text); + border-color: var(--exercise-border); +} + +html.dark-mode .alert-warning { + background-color: rgba(255, 193, 7, 0.12); + border-color: rgba(255, 193, 7, 0.28); + color: #f3d98b; +} + +html.dark-mode .alert-warning a { + color: #ffd76a; +} + +html.dark-mode .alert-warning code { + background-color: rgba(255, 193, 7, 0.08) !important; + color: #ffe08a; + border-color: rgba(255, 193, 7, 0.2); +} + +html.dark-mode .alert-info { + background-color: rgba(56, 189, 248, 0.12); + border-color: rgba(56, 189, 248, 0.28); + color: #9edcff; +} + +html.dark-mode .alert-info a { + color: #7dd3fc; +} + +html.dark-mode .alert-info code { + background-color: rgba(56, 189, 248, 0.08) !important; + color: #b6e7ff; + border-color: rgba(56, 189, 248, 0.2); +} + +html.dark-mode .alert-success { + background-color: rgba(34, 197, 94, 0.12); + border-color: rgba(34, 197, 94, 0.28); + color: #9ee6b3; +} + +html.dark-mode .alert-success a { + color: #86efac; +} + +html.dark-mode .alert-success code { + background-color: rgba(34, 197, 94, 0.08) !important; + color: #b8f5c8; + border-color: rgba(34, 197, 94, 0.2); +} + +html.dark-mode .alert-danger { + background-color: rgba(239, 68, 68, 0.12); + border-color: rgba(239, 68, 68, 0.28); + color: #ffb4b4; +} + +html.dark-mode .alert-danger a { + color: #fca5a5; +} + +html.dark-mode .alert-danger code { + background-color: rgba(239, 68, 68, 0.08) !important; + color: #ffc7c7; + border-color: rgba(239, 68, 68, 0.2); +} + +.page-inner .exercise .header { + background-color: var(--exercise-header-bg); + color: var(--exercise-header-text); +} + +.page-inner .exercise .message { + color: var(--exercise-text); +} + +.page-inner .exercise .editor { + background-color: var(--exercise-editor-bg); + border-top-color: var(--exercise-editor-border); + border-bottom-color: var(--exercise-editor-border); +} + +pre, +code { + background-color: var(--code-bg) !important; +} + + +.book-body .markdown-section a { + color: var(--link-color); +} + +.book-body .markdown-section a:hover, +.book-body .markdown-section a:focus { + color: var(--link-color); +} + +.book-body .markdown-section hr { + background-color: var(--hr-color); +} + +.book-body .markdown-section blockquote { + color: var(--muted-text); + border-left-color: var(--border-color); +} + +/* Inline code readability (GitBook theme sets its own; this keeps it consistent with your vars) */ +.book-body .markdown-section :not(pre) > code { + color: var(--text-color); + border: 1px solid var(--border-color); +} + +/* Tables */ +.book-body .markdown-section table { + width: 100%; + border-collapse: collapse; + border-spacing: 0; +} + +.book-body .markdown-section table th, +.book-body .markdown-section table td { + border: 1px solid var(--border-color); +} + +.book-body .markdown-section table thead tr { + background-color: var(--table-header-bg); +} + +.book-body .markdown-section table tbody tr { + background-color: var(--table-row-bg); +} + +.book-body .markdown-section table tbody tr:nth-child(2n) { + background-color: var(--table-row-alt-bg); +} + +html.dark-mode .language-selector-container { + background-color: var(--bg-color); + color: var(--text-color); +} + +html.dark-mode .language-card { + background-color: #1f2124; + border: 1px solid var(--border-color); + color: var(--text-color); + box-shadow: 0 4px 14px rgba(0, 0, 0, 0.22); +} + +html.dark-mode .language-card:hover, +html.dark-mode .language-card:focus { + background-color: #23262a; + border-color: #3a4046; + box-shadow: 0 8px 20px rgba(0, 0, 0, 0.28); +} + +html.dark-mode .language-card a, +html.dark-mode .language-card h1, +html.dark-mode .language-card h2, +html.dark-mode .language-card h3, +html.dark-mode .language-card p, +html.dark-mode .language-card span { + color: var(--text-color); +} + +html.dark-mode .section-header h2 { + color: var(--text-color); +} + +/* Toggle Button Styling */ +#dark-mode-toggle { + cursor: pointer; + border: none; + background: transparent; + font-size: 1.2rem; + line-height: 1; + margin-left: auto; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 6px 10px; +} + +html.dark-mode .icon-sun { + display: inline-flex; +} + +html.dark-mode .icon-moon { + display: none; +} + +html:not(.dark-mode) .icon-sun { + display: none; +} + +html:not(.dark-mode) .icon-moon { + display: inline-flex; +} \ No newline at end of file diff --git a/website/dark-mode.js b/website/dark-mode.js new file mode 100644 index 00000000..4e5b51be --- /dev/null +++ b/website/dark-mode.js @@ -0,0 +1,39 @@ +(function () { + + function applyStoredTheme() { + var savedTheme = localStorage.getItem("theme"); + var shouldUseDark = + savedTheme === "dark" || + (!savedTheme && window.matchMedia("(prefers-color-scheme: dark)").matches); + + document.documentElement.classList.toggle("dark-mode", shouldUseDark); + } + + function bindDarkModeToggle() { + var toggle = document.getElementById("dark-mode-toggle"); + + if (!toggle || toggle.dataset.darkModeBound === "true") { + return; + } + + toggle.dataset.darkModeBound = "true"; + + toggle.addEventListener("click", function () { + var isDark = document.documentElement.classList.toggle("dark-mode"); + localStorage.setItem("theme", isDark ? "dark" : "light"); + }); + } + + function initDarkMode() { + applyStoredTheme(); + bindDarkModeToggle(); + } + + initDarkMode(); + + document.addEventListener("DOMContentLoaded", initDarkMode); + + if (typeof gitbook !== "undefined" && gitbook.events && gitbook.events.bind) { + gitbook.events.bind("page.change", initDarkMode); + } +})(); \ No newline at end of file From b56e11d3e540f6869b77d3d8e2e306108ee6843a Mon Sep 17 00:00:00 2001 From: Michael Hughes Date: Sat, 7 Mar 2026 18:30:27 -0700 Subject: [PATCH 2/2] fix: add body background color in dark mode --- website/dark-mode.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/website/dark-mode.css b/website/dark-mode.css index df9ce60d..aa805e0d 100644 --- a/website/dark-mode.css +++ b/website/dark-mode.css @@ -261,6 +261,10 @@ html.dark-mode .section-header h2 { color: var(--text-color); } +html.dark-mode body { + background-color: var(--bg-color); +} + /* Toggle Button Styling */ #dark-mode-toggle { cursor: pointer;