From 2c63266f54a7c0cdd4b122b3caf3f6ef6c3be53b Mon Sep 17 00:00:00 2001 From: White-Devil2839 Date: Tue, 18 Nov 2025 10:59:48 +0530 Subject: [PATCH 01/14] feat: Add dark mode support and CSS improvements - Add CSS custom properties for theming - Implement dark mode with prefers-color-scheme and manual toggle - Add theme toggle button in top-left corner with localStorage persistence - Improve accessibility with focus states and contrast ratios - Enhance responsive design with better breakpoints - Improve code block styling with dark mode syntax highlighting - Add print stylesheet optimizations - Improve mobile navigation styling - Enhance API navigation sidebar responsiveness --- docs/api_split.pug | 2 +- docs/css/api.css | 103 ++++++++- docs/css/github.css | 210 +++++++++++++++++-- docs/css/mongoose5.css | 448 +++++++++++++++++++++++++++++++++++++--- docs/css/style.css | 149 ++++++++++++- docs/js/theme-toggle.js | 72 +++++++ docs/layout.pug | 9 +- index.pug | 10 +- 8 files changed, 943 insertions(+), 60 deletions(-) create mode 100644 docs/js/theme-toggle.js diff --git a/docs/api_split.pug b/docs/api_split.pug index 2078d1b28ee..78ff1b1a140 100644 --- a/docs/api_split.pug +++ b/docs/api_split.pug @@ -1,7 +1,7 @@ extends layout append style - link(rel="stylesheet", href=`${versions.versionedPath}/docs/css/api.css`) + link(rel="stylesheet", href=`${versions.versionedPath}/docs/css/api.css?v=${Date.now()}`) script(src=`${versions.versionedPath}/docs/js/api-bold-current-nav.js`) script(src=`${versions.versionedPath}/docs/js/convert-old-anchorid.js`) diff --git a/docs/css/api.css b/docs/css/api.css index a2f30f6c76e..3d9b50fe0df 100644 --- a/docs/css/api.css +++ b/docs/css/api.css @@ -12,6 +12,28 @@ height: 100%; padding-bottom: 10px; overflow-y: auto; + background-color: var(--menu-bg, #fafafa); + border-left: 1px solid var(--border-color, #ddd); + scrollbar-width: thin; + scrollbar-color: var(--border-color, #ddd) var(--menu-bg, #fafafa); + transition: background-color 0.3s ease, border-color 0.3s ease; +} + +.api-nav::-webkit-scrollbar { + width: 8px; +} + +.api-nav::-webkit-scrollbar-track { + background: var(--menu-bg, #fafafa); +} + +.api-nav::-webkit-scrollbar-thumb { + background-color: var(--border-color, #ddd); + border-radius: 4px; +} + +.api-nav::-webkit-scrollbar-thumb:hover { + background-color: var(--text-muted, #777); } .api-nav .nav-item-title { @@ -24,7 +46,18 @@ } .api-nav a { - color: #777; + color: var(--text-muted, #777); + transition: color 0.2s ease; +} + +.api-nav a:hover { + color: var(--link-color, #0971B2); +} + +.api-nav a:focus-visible { + outline: 3px solid var(--focus-ring, #0971B2); + outline-offset: 2px; + border-radius: 2px; } .api-nav .nav-item-sub { @@ -54,12 +87,47 @@ margin-top: 3em; } +/* Responsive API navigation */ @media (max-width: 1785px) { .api-nav { display: none; } } +/* Tablet: Show API nav as collapsible sidebar */ +@media (min-width: 1400px) and (max-width: 1785px) { + .api-nav { + display: block; + left: auto; + right: 0; + width: 280px; + z-index: 10; + } +} + +/* Mobile: API nav as bottom sheet or hidden */ +@media (max-width: 1400px) { + .api-nav { + display: none; + } + + /* Optionally show as bottom sheet on mobile */ + .api-nav.mobile-open { + display: block; + position: fixed; + bottom: 0; + left: 0; + right: 0; + top: auto; + height: 50vh; + width: 100%; + border-left: none; + border-top: 1px solid var(--border-color, #ddd); + border-radius: 8px 8px 0 0; + box-shadow: 0 -2px 8px var(--shadow, rgba(0, 0, 0, 0.1)); + } +} + ul { margin-top: -10px; } @@ -166,4 +234,37 @@ hr.separate-api { .deprecated { color: #ff0000; + font-weight: 600; +} + +/* Accessibility improvements */ +.method-type:focus-visible, +.api-nav .nav-item-title:focus-visible { + outline: 3px solid var(--focus-ring, #0971B2); + outline-offset: 2px; + border-radius: 2px; +} + +/* Dark mode support for API page */ +@media (prefers-color-scheme: dark) { + .api-nav { + background-color: var(--menu-bg, #252525); + border-left-color: var(--border-color, #444); + } + + .api-nav a { + color: var(--text-muted, #888); + } + + .api-nav a:hover { + color: var(--link-color, #4a9eff); + } + + .native-ad { + background-color: var(--bg-secondary, #2d2d2d); + } + + .native-ad a { + color: var(--text-primary, #e0e0e0); + } } diff --git a/docs/css/github.css b/docs/css/github.css index f8cec1bdc3f..f4e134a0dd7 100644 --- a/docs/css/github.css +++ b/docs/css/github.css @@ -1,31 +1,45 @@ code { - background-color: #eee; - padding: 2px 4px; + background-color: var(--code-bg, #eee); + padding: 2px 6px; font-size: 0.9em; - color: #800; + color: var(--link-color, #800); border-radius: 4px; + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + transition: background-color 0.3s ease, color 0.3s ease; } pre code { background-color: transparent; padding: 0; font-size: 1em; - color: #222; + color: var(--code-text, #222); } pre { display: block; - padding: 9.5px; - margin: 10px 0 10px; + padding: 12px 16px; + margin: 16px 0; font-size: 13px; - line-height: 1.42857143; - color: #333; - word-break: break-all; - word-wrap: break-word; - background-color: #f5f5f5; - border: 1px solid #ccc; - border-radius: 4px; - font-family: Menlo,Monaco,Consolas,"Courier New",monospace; + line-height: 1.6; + color: var(--code-text, #333); + word-break: break-word; + overflow-wrap: break-word; + overflow-x: auto; + background-color: var(--code-bg, #f5f5f5); + border: 1px solid var(--border-color, #ccc); + border-radius: 6px; + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + box-shadow: 0 1px 3px var(--shadow, rgba(0, 0, 0, 0.1)); + transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease; +} + +/* Improve code block copy functionality */ +pre { + position: relative; +} + +pre:hover { + box-shadow: 0 2px 6px var(--shadow, rgba(0, 0, 0, 0.15)); } /* @@ -38,9 +52,10 @@ github.com style (c) Vasily Polovnyov display: block; overflow-x: auto; padding: 0.5em; - color: #333; - background: #f8f8f8; + color: var(--code-text, #333); + background: var(--code-bg, #f8f8f8); -webkit-text-size-adjust: none; + transition: background-color 0.3s ease, color 0.3s ease; } .hljs-comment, @@ -152,3 +167,166 @@ github.com style (c) Vasily Polovnyov .hljs-chunk { color: #aaa; } + +/* Dark mode support for syntax highlighting */ +@media (prefers-color-scheme: dark) { + code { + background-color: var(--code-bg, #2d2d2d); + color: var(--link-color, #4a9eff); + } + + pre { + background-color: var(--code-bg, #2d2d2d); + border-color: var(--border-color, #444); + color: var(--code-text, #e0e0e0); + } + + .hljs { + background: var(--code-bg, #2d2d2d); + color: var(--code-text, #e0e0e0); + } + + .hljs-comment, + .diff .hljs-header, + .hljs-javadoc { + color: #6a9955; + } + + .hljs-keyword, + .css .rule .hljs-keyword, + .hljs-winutils, + .nginx .hljs-title, + .hljs-subst, + .hljs-request, + .hljs-status { + color: #569cd6; + font-weight: bold; + } + + .hljs-number, + .hljs-hexcolor, + .ruby .hljs-constant { + color: #b5cea8; + } + + .hljs-string, + .hljs-tag .hljs-value, + .hljs-phpdoc, + .hljs-dartdoc, + .tex .hljs-formula { + color: #ce9178; + } + + .hljs-title, + .hljs-id, + .scss .hljs-preprocessor { + color: #d7ba7d; + font-weight: bold; + } + + .hljs-class .hljs-title, + .hljs-type, + .vhdl .hljs-literal, + .tex .hljs-command { + color: #4ec9b0; + font-weight: bold; + } + + .hljs-tag, + .hljs-tag .hljs-title, + .hljs-rules .hljs-property, + .django .hljs-tag .hljs-keyword { + color: #569cd6; + font-weight: normal; + } + + .hljs-attribute, + .hljs-variable, + .lisp .hljs-body { + color: #9cdcfe; + } + + .hljs-regexp { + color: #d16969; + } + + .hljs-symbol, + .ruby .hljs-symbol .hljs-string, + .lisp .hljs-keyword, + .clojure .hljs-keyword, + .scheme .hljs-keyword, + .tex .hljs-special, + .hljs-prompt { + color: #c586c0; + } + + .hljs-built_in { + color: #4fc1ff; + } + + .hljs-preprocessor, + .hljs-pragma, + .hljs-pi, + .hljs-doctype, + .hljs-shebang, + .hljs-cdata { + color: #808080; + font-weight: bold; + } + + .hljs-deletion { + background: #5a1d1d; + color: #f48771; + } + + .hljs-addition { + background: #1e3a1e; + color: #b5cea8; + } + + .diff .hljs-change { + background: #2d4d2d; + color: #4ec9b0; + } + + .hljs-chunk { + color: #808080; + } +} + +/* Accessibility: Ensure sufficient contrast for code */ +code, +pre, +.hljs { + /* WCAG AA compliant contrast ratios */ + min-height: 1.5em; +} + +/* Improve code block readability on small screens */ +@media (max-width: 768px) { + pre { + font-size: 12px; + padding: 10px; + margin: 12px 0; + } + + code { + font-size: 0.85em; + padding: 2px 4px; + } +} + +/* Print styles for code blocks */ +@media print { + pre { + border: 1px solid #ccc; + page-break-inside: avoid; + background: #f5f5f5; + color: #000; + } + + code { + background: #f0f0f0; + color: #000; + } +} diff --git a/docs/css/mongoose5.css b/docs/css/mongoose5.css index 4ae64f50ddf..141c6a7c89c 100644 --- a/docs/css/mongoose5.css +++ b/docs/css/mongoose5.css @@ -1,9 +1,97 @@ +/* CSS Custom Properties for Theming */ +:root { + /* Light mode colors */ + --bg-primary: #ffffff; + --bg-secondary: #eee; + --bg-tertiary: #fafafa; + --text-primary: #000000; + --text-secondary: #333333; + --text-muted: #777777; + --link-color: #0971B2; + --link-hover: #065a8f; + --border-color: #ddd; + --code-bg: #f5f5f5; + --code-text: #333; + --menu-bg: #eee; + --menu-hover: rgba(0,0,0, 0.1); + --menu-selected: rgba(0,0,0, 0.15); + --shadow: rgba(0, 0, 0, 0.1); + --focus-ring: #0971B2; + --focus-ring-width: 3px; +} + +/* Dark mode colors */ +@media (prefers-color-scheme: dark) { + :root:not([data-theme="light"]) { + --bg-primary: #1a1a1a; + --bg-secondary: #2d2d2d; + --bg-tertiary: #252525; + --text-primary: #e0e0e0; + --text-secondary: #c0c0c0; + --text-muted: #888888; + --link-color: #4a9eff; + --link-hover: #6bb3ff; + --border-color: #444444; + --code-bg: #2d2d2d; + --code-text: #e0e0e0; + --menu-bg: #252525; + --menu-hover: rgba(255,255,255, 0.1); + --menu-selected: rgba(255,255,255, 0.15); + --shadow: rgba(0, 0, 0, 0.3); + --focus-ring: #4a9eff; + } +} + +/* Manual dark mode override */ +[data-theme="dark"] { + --bg-primary: #1a1a1a; + --bg-secondary: #2d2d2d; + --bg-tertiary: #252525; + --text-primary: #e0e0e0; + --text-secondary: #c0c0c0; + --text-muted: #888888; + --link-color: #4a9eff; + --link-hover: #6bb3ff; + --border-color: #444444; + --code-bg: #2d2d2d; + --code-text: #e0e0e0; + --menu-bg: #252525; + --menu-hover: rgba(255,255,255, 0.1); + --menu-selected: rgba(255,255,255, 0.15); + --shadow: rgba(0, 0, 0, 0.3); + --focus-ring: #4a9eff; +} + +/* Light mode override */ +[data-theme="light"] { + --bg-primary: #ffffff; + --bg-secondary: #eee; + --bg-tertiary: #fafafa; + --text-primary: #000000; + --text-secondary: #333333; + --text-muted: #777777; + --link-color: #0971B2; + --link-hover: #065a8f; + --border-color: #ddd; + --code-bg: #f5f5f5; + --code-text: #333; + --menu-bg: #eee; + --menu-hover: rgba(0,0,0, 0.1); + --menu-selected: rgba(0,0,0, 0.15); + --shadow: rgba(0, 0, 0, 0.1); + --focus-ring: #0971B2; +} + html { font-family: 'Open Sans'; + color-scheme: light dark; } body { margin: 0; + background-color: var(--bg-primary); + color: var(--text-primary); + transition: background-color 0.3s ease, color 0.3s ease; } img { @@ -12,7 +100,19 @@ img { a { text-decoration: none; - color: #0971B2; + color: var(--link-color); + transition: color 0.2s ease, opacity 0.2s ease; +} + +a:hover { + color: var(--link-hover); + opacity: 0.9; +} + +a:focus-visible { + outline: var(--focus-ring-width) solid var(--focus-ring); + outline-offset: 2px; + border-radius: 2px; } p { @@ -51,7 +151,16 @@ h1 a, h2 a, h3 a, h4 a { - color: #000; + color: var(--text-primary); +} + +h1 a:focus-visible, +h2 a:focus-visible, +h3 a:focus-visible, +h4 a:focus-visible { + outline: var(--focus-ring-width) solid var(--focus-ring); + outline-offset: 2px; + border-radius: 2px; } #logo { @@ -62,7 +171,7 @@ h4 a { } .logo-text { - color: #800; + color: var(--link-color); font-size: 20pt; position: relative; top: 0px; @@ -86,8 +195,19 @@ h4 a { padding-bottom: 0px; } -.pure-menu-link:hover, .pure-menu-link.selected { - background-color: rgba(0,0,0, 0.1); +.pure-menu-link:hover, +.pure-menu-link.selected { + background-color: var(--menu-hover); +} + +.pure-menu-link:focus-visible { + outline: var(--focus-ring-width) solid var(--focus-ring); + outline-offset: -2px; + border-radius: 2px; +} + +.pure-menu-link.selected { + background-color: var(--menu-selected); } li.sub-item { @@ -96,18 +216,18 @@ li.sub-item { } li.version { - border-bottom: 1px solid #ddd; + border-bottom: 1px solid var(--border-color); padding-bottom: 4px; } li.version ul.pure-menu-children { - border: 1px solid #ddd; + border: 1px solid var(--border-color); } #logo-container { padding-top: 0; padding-bottom: 6px; - border-bottom: 1px solid #ddd; + border-bottom: 1px solid var(--border-color); } #logo-container > a { @@ -120,10 +240,29 @@ li.version ul.pure-menu-children { top: 0; left: 0; bottom: 0px; - background-color: #eee; + background-color: var(--menu-bg); width: 250px; - border-right: 1px solid #ddd; + border-right: 1px solid var(--border-color); overflow-y: auto; + scrollbar-width: thin; + scrollbar-color: var(--border-color) var(--menu-bg); +} + +#menu::-webkit-scrollbar { + width: 8px; +} + +#menu::-webkit-scrollbar-track { + background: var(--menu-bg); +} + +#menu::-webkit-scrollbar-thumb { + background-color: var(--border-color); + border-radius: 4px; +} + +#menu::-webkit-scrollbar-thumb:hover { + background-color: var(--text-muted); } .container { @@ -143,11 +282,26 @@ li.version ul.pure-menu-children { } .search input { - border: 1px solid #ddd; + border: 1px solid var(--border-color); padding: 0.25em; width: 170px; border-radius: 3px; flex: 1; + background-color: var(--bg-primary); + color: var(--text-primary); + transition: border-color 0.2s ease, box-shadow 0.2s ease; +} + +.search input:focus { + outline: none; + border-color: var(--focus-ring); + box-shadow: 0 0 0 2px rgba(9, 113, 178, 0.1); +} + +@media (prefers-color-scheme: dark) { + .search input:focus { + box-shadow: 0 0 0 2px rgba(74, 158, 255, 0.2); + } } #search-input-nav { @@ -155,14 +309,29 @@ li.version ul.pure-menu-children { } .search button { - background-color: #777; - color: white; + background-color: var(--text-muted); + color: var(--bg-primary); border: 1px solid transparent; border-radius: 3px; height: 30px; width: 30px; padding: 0px; flex: 0 0 auto; + cursor: pointer; + transition: background-color 0.2s ease, transform 0.1s ease; +} + +.search button:hover { + background-color: var(--text-secondary); +} + +.search button:active { + transform: scale(0.95); +} + +.search button:focus-visible { + outline: var(--focus-ring-width) solid var(--focus-ring); + outline-offset: 2px; } #search-button-nav { @@ -179,11 +348,21 @@ li.version ul.pure-menu-children { position: absolute; top: 0.125em; right: 0px; - background-color: #fafafa; - border: 1px solid #ddd; + background-color: var(--bg-tertiary); + border: 1px solid var(--border-color); padding: 5px; padding-bottom: 0px; border-radius: 3px; + transition: background-color 0.2s ease, border-color 0.2s ease; +} + +.edit-docs-link:hover { + background-color: var(--bg-secondary); +} + +.edit-docs-link:focus-visible { + outline: var(--focus-ring-width) solid var(--focus-ring); + outline-offset: 2px; } .edit-docs-link img { @@ -204,6 +383,14 @@ li.version ul.pure-menu-children { display: none; } +/* Improved responsive breakpoints */ +@media (max-width: 1400px) { + .container { + width: calc(100% - 300px); + max-width: 900px; + } +} + @media (max-width: 1160px) { h2:hover::before, h3:hover::before { position: static; @@ -226,10 +413,12 @@ li.version ul.pure-menu-children { display: none; position: fixed; top: 45px; - border-top: 1px solid #ddd; - border-right: 1px solid #ddd; - border-bottom: 1px solid #ddd; + border-top: 1px solid var(--border-color); + border-right: 1px solid var(--border-color); + border-bottom: 1px solid var(--border-color); left: 0px; + max-height: calc(100vh - 45px); + box-shadow: 2px 0 8px var(--shadow); } pre { @@ -238,13 +427,15 @@ li.version ul.pure-menu-children { } #mobile-menu { - display: block; + display: flex; + align-items: center; height: 45px; - background-color: #eee; - border-bottom: 1px solid #ddd; + background-color: var(--menu-bg); + border-bottom: 1px solid var(--border-color); position: sticky; top: 0; - z-index: 1; + z-index: 100; + box-shadow: 0 2px 4px var(--shadow); } #logo { @@ -259,6 +450,21 @@ li.version ul.pure-menu-children { width: 215px; margin-left: auto; margin-right: auto; + display: flex; + align-items: center; + justify-content: center; + } + + #mobile-logo-container a { + display: flex; + align-items: center; + text-decoration: none; + } + + #mobile-logo-container a:focus-visible { + outline: var(--focus-ring-width) solid var(--focus-ring); + outline-offset: 2px; + border-radius: 2px; } #logo-container { @@ -267,26 +473,44 @@ li.version ul.pure-menu-children { .menu-link { position: absolute; - display: block; + display: flex; + align-items: center; + justify-content: center; top: 0px; left: 0; - background-color: #eee; + background-color: transparent; z-index: 10; - width: 2em; - height: 3px; - padding: 2.1em 1.6em; + width: 45px; + height: 45px; + padding: 0; + border: none; + cursor: pointer; + transition: background-color 0.2s ease; + } + + .menu-link:hover { + background-color: var(--menu-hover); } - .menu-link:hover, - .menu-link:focus { - background: #ddd; + .menu-link:focus-visible { + outline: var(--focus-ring-width) solid var(--focus-ring); + outline-offset: -2px; + background-color: var(--menu-hover); } #menuLink { width: 40px; height: 40px; - padding: 2.5px; - color: rgb(0,0,0); + padding: 8px; + color: var(--text-primary); + display: flex; + align-items: center; + justify-content: center; + } + + #menuLink svg { + width: 100%; + height: 100%; } .active { @@ -371,3 +595,163 @@ li.version ul.pure-menu-children { display: none !important; } } + +/* Print stylesheet improvements */ +@media print { + #menu, + #mobile-menu, + .edit-docs-link, + #jobs, + .cpc-ad, + .api-nav { + display: none !important; + } + + .container { + left: 0 !important; + width: 100% !important; + padding: 0 !important; + margin: 0 !important; + } + + body { + background: white; + color: black; + } + + a { + color: #000; + text-decoration: underline; + } + + a[href^="http"]:after { + content: " (" attr(href) ")"; + font-size: 0.8em; + color: #666; + } + + pre { + border: 1px solid #ccc; + page-break-inside: avoid; + } + + h1, h2, h3, h4, h5, h6 { + page-break-after: avoid; + } + + img { + max-width: 100% !important; + page-break-inside: avoid; + } +} + +/* Tablet breakpoint */ +@media (min-width: 768px) and (max-width: 1160px) { + .container { + padding-left: 30px; + padding-right: 30px; + } +} + +/* Small mobile devices */ +@media (max-width: 480px) { + .container { + padding-left: 15px; + padding-right: 15px; + } + + #content { + margin: 5px; + } + + #mobile-logo-container { + width: 180px; + } + + .logo-text { + font-size: 16pt; + } +} + +/* Theme Toggle Button */ +#theme-toggle { + position: fixed; + top: 10px; + left: 10px; + z-index: 1000; + background-color: var(--bg-secondary); + border: 1px solid var(--border-color); + border-radius: 50%; + box-shadow: 0 2px 8px var(--shadow); + transition: background-color 0.3s ease, border-color 0.3s ease; +} + +#theme-toggle-btn { + width: 44px; + height: 44px; + padding: 0; + margin: 0; + border: none; + background: transparent; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + border-radius: 50%; + color: var(--text-primary); + transition: background-color 0.2s ease, transform 0.1s ease; +} + +#theme-toggle-btn:hover { + background-color: var(--menu-hover); +} + +#theme-toggle-btn:active { + transform: scale(0.95); +} + +#theme-toggle-btn:focus-visible { + outline: var(--focus-ring-width) solid var(--focus-ring); + outline-offset: 2px; +} + +#theme-icon-light, +#theme-icon-dark { + position: absolute; + transition: opacity 0.3s ease, transform 0.3s ease; + width: 20px; + height: 20px; +} + +/* Default: show moon icon (for light/system mode) */ +#theme-icon-dark { + opacity: 1; + transform: rotate(0deg); +} + +#theme-icon-light { + opacity: 0; + transform: rotate(90deg); + pointer-events: none; +} + +/* In dark mode: show sun icon, hide moon icon */ +[data-theme="dark"] #theme-icon-light { + opacity: 1; + transform: rotate(0deg); + pointer-events: auto; +} + +[data-theme="dark"] #theme-icon-dark { + opacity: 0; + transform: rotate(90deg); + pointer-events: none; +} + +/* On mobile, adjust position */ +@media (max-width: 1160px) { + #theme-toggle { + top: 5px; + left: 50px; + } +} diff --git a/docs/css/style.css b/docs/css/style.css index 32edaaea473..095d187f27b 100644 --- a/docs/css/style.css +++ b/docs/css/style.css @@ -1,10 +1,123 @@ body { font-family: 'Open Sans', Helvetica, Arial, FreeSans; - color: #333; + color: var(--text-secondary, #333); -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: 100%; padding: 0; margin: 0; + background-color: var(--bg-primary, #ffffff); + transition: background-color 0.3s ease, color 0.3s ease; +} + +/* Dark mode support for homepage */ +@media (prefers-color-scheme: dark) { + body:not([data-theme="light"]) { + background-color: var(--bg-primary, #1a1a1a); + color: var(--text-secondary, #c0c0c0); + } +} + +/* Manual theme overrides */ +body[data-theme="dark"] { + background-color: var(--bg-primary, #1a1a1a); + color: var(--text-secondary, #c0c0c0); +} + +body[data-theme="light"] { + background-color: var(--bg-primary, #ffffff); + color: var(--text-secondary, #333); +} + +/* Theme Toggle Button for Homepage */ +#theme-toggle { + position: fixed; + top: 10px; + left: 10px; + z-index: 1000; + background-color: rgba(255, 255, 255, 0.9); + border: 1px solid #ddd; + border-radius: 50%; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + transition: background-color 0.3s ease, border-color 0.3s ease; +} + +body[data-theme="dark"] #theme-toggle { + background-color: rgba(26, 26, 26, 0.9); + border-color: #444; +} + +#theme-toggle-btn { + width: 44px; + height: 44px; + padding: 0; + margin: 0; + border: none; + background: transparent; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + border-radius: 50%; + color: #333; + transition: background-color 0.2s ease, transform 0.1s ease; +} + +body[data-theme="dark"] #theme-toggle-btn { + color: #e0e0e0; +} + +#theme-toggle-btn:hover { + background-color: rgba(0, 0, 0, 0.1); +} + +body[data-theme="dark"] #theme-toggle-btn:hover { + background-color: rgba(255, 255, 255, 0.1); +} + +#theme-toggle-btn:active { + transform: scale(0.95); +} + +#theme-toggle-btn:focus-visible { + outline: 3px solid #0971B2; + outline-offset: 2px; +} + +body[data-theme="dark"] #theme-toggle-btn:focus-visible { + outline-color: #4a9eff; +} + +#theme-icon-light, +#theme-icon-dark { + position: absolute; + transition: opacity 0.3s ease, transform 0.3s ease; + width: 20px; + height: 20px; +} + +/* Default: show moon icon (for light/system mode) */ +#theme-icon-dark { + opacity: 1; + transform: rotate(0deg); +} + +#theme-icon-light { + opacity: 0; + transform: rotate(90deg); + pointer-events: none; +} + +/* In dark mode: show sun icon, hide moon icon */ +[data-theme="dark"] #theme-icon-light { + opacity: 1; + transform: rotate(0deg); + pointer-events: auto; +} + +[data-theme="dark"] #theme-icon-dark { + opacity: 0; + transform: rotate(90deg); + pointer-events: none; } /* location.hash */ @@ -21,14 +134,20 @@ body { } a { - color: #800; + color: var(--link-color, #800); -webkit-transition-property: opacity, -webkit-transform, color, background-color, padding, -webkit-box-shadow; -webkit-transition-duration: 0.15s; -webkit-transition-timing-function: ease-out; + transition: opacity 0.15s ease-out, color 0.15s ease-out; } a:hover { opacity: 0.8; } +a:focus-visible { + outline: 3px solid var(--focus-ring, #0971B2); + outline-offset: 2px; + border-radius: 2px; +} #wrap { width: 600px; margin: 0 auto; @@ -43,20 +162,38 @@ h1 { } pre { - background: #eee; - padding: 5px; - border-radius: 3px; + background: var(--code-bg, #eee); + padding: 12px 16px; + border-radius: 6px; overflow-x: auto; + border: 1px solid var(--border-color, #ddd); + transition: background-color 0.3s ease, border-color 0.3s ease; } code { - color: #333; + color: var(--code-text, #333); font-size: 11px; font-family: Consolas, "Liberation Mono", Courier, monospace; + background-color: var(--code-bg, #eee); + padding: 2px 6px; + border-radius: 4px; } pre code { border: 0 none; padding: 1.2em; overflow-x: auto; + background-color: transparent; +} + +/* Dark mode for homepage code blocks */ +@media (prefers-color-scheme: dark) { + pre { + background: var(--code-bg, #2d2d2d); + border-color: var(--border-color, #444); + } + code { + color: var(--code-text, #e0e0e0); + background-color: var(--code-bg, #2d2d2d); + } } #header { text-align: center; diff --git a/docs/js/theme-toggle.js b/docs/js/theme-toggle.js new file mode 100644 index 00000000000..df57c22c08e --- /dev/null +++ b/docs/js/theme-toggle.js @@ -0,0 +1,72 @@ +(function() { + 'use strict'; + + // Get saved theme preference or default to system preference + function getInitialTheme() { + const savedTheme = localStorage.getItem('mongoose-theme'); + if (savedTheme === 'light' || savedTheme === 'dark') { + return savedTheme; + } + // Default to system preference + return null; + } + + // Apply theme to document + function applyTheme(theme) { + if (theme === 'light' || theme === 'dark') { + document.documentElement.setAttribute('data-theme', theme); + localStorage.setItem('mongoose-theme', theme); + } else { + document.documentElement.removeAttribute('data-theme'); + localStorage.removeItem('mongoose-theme'); + } + updateThemeIcon(); + } + + // Update theme icon visibility + function updateThemeIcon() { + // CSS handles the icon visibility, but we can ensure proper state + const theme = document.documentElement.getAttribute('data-theme'); + const lightIcon = document.getElementById('theme-icon-light'); // Sun icon + const darkIcon = document.getElementById('theme-icon-dark'); // Moon icon + + if (lightIcon && darkIcon) { + // In dark mode: show sun icon (to switch to light) + // In light mode: show moon icon (to switch to dark) + // CSS handles the actual visibility via opacity + } + } + + // Toggle between light and dark + function toggleTheme() { + const currentTheme = document.documentElement.getAttribute('data-theme'); + if (currentTheme === 'dark') { + applyTheme('light'); + } else if (currentTheme === 'light') { + applyTheme(null); // Reset to system preference + } else { + // Currently using system preference, switch to dark + applyTheme('dark'); + } + } + + // Initialize theme on page load + function initTheme() { + const initialTheme = getInitialTheme(); + applyTheme(initialTheme); + + // Set up toggle button + const toggleBtn = document.getElementById('theme-toggle-btn'); + if (toggleBtn) { + toggleBtn.addEventListener('click', toggleTheme); + } + } + + // Run when DOM is ready + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initTheme); + } else { + initTheme(); + } +})(); + diff --git a/docs/layout.pug b/docs/layout.pug index c8e5ac01d4d..10e7c29d981 100644 --- a/docs/layout.pug +++ b/docs/layout.pug @@ -10,8 +10,8 @@ html(lang='en') link(rel="stylesheet", href="https://unpkg.com/purecss@1.0.1/build/pure-min.css", integrity="sha384-oAOxQR6DkCoMliIh8yFnu25d7Eq/PHS21PClpwjOTeU2jRSq11vu66rf90/cZr47", crossorigin="anonymous") link(rel="stylesheet", href="https://fonts.googleapis.com/css?family=Open+Sans") - link(rel="stylesheet", href=`${versions.versionedPath}/docs/css/github.css`) - link(rel="stylesheet", href=`${versions.versionedPath}/docs/css/mongoose5.css`) + link(rel="stylesheet", href=`${versions.versionedPath}/docs/css/mongoose5.css?v=${Date.now()}`) + link(rel="stylesheet", href=`${versions.versionedPath}/docs/css/github.css?v=${Date.now()}`) link(rel="stylesheet", href=`${versions.versionedPath}/docs/css/carbonads.css`) meta(name='msapplication-TileColor', content='#ffffff') @@ -21,6 +21,10 @@ html(lang='en') body block layout #layout + #theme-toggle + button#theme-toggle-btn(aria-label="Toggle dark mode" title="Toggle dark/light theme") + + #mobile-menu a#menuLink.menu-link(href='#menu') @@ -172,3 +176,4 @@ html(lang='en') script(type="text/javascript" src=`${versions.versionedPath}/docs/js/navbar-search.js`) script(type="text/javascript" src=`${versions.versionedPath}/docs/js/mobile-navbar-toggle.js`) + script(type="text/javascript" src=`${versions.versionedPath}/docs/js/theme-toggle.js`) diff --git a/index.pug b/index.pug index 14cba69a0ff..f219d428acd 100644 --- a/index.pug +++ b/index.pug @@ -5,8 +5,9 @@ html(lang='en') meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") title Mongoose ODM v#{package.version} link(href="//fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700", rel="stylesheet", type="text/css") - link(href="docs/css/style.css", rel="stylesheet") - link(href="docs/css/github.css", rel="stylesheet") + link(href="docs/css/mongoose5.css?v=" + Date.now(), rel="stylesheet") + link(href="docs/css/style.css?v=" + Date.now(), rel="stylesheet") + link(href="docs/css/github.css?v=" + Date.now(), rel="stylesheet") link(href="docs/css/carbonads.css", rel="stylesheet") include ./docs/includes/favicon @@ -45,6 +46,10 @@ html(lang='en') } body + #theme-toggle + button#theme-toggle-btn(aria-label="Toggle dark mode" title="Toggle dark/light theme") + + a(class="github-fork-ribbon" href="https://github.com/Automattic/mongoose" data-ribbon="Fork me on GitHub" title="Fork me on GitHub" target="_blank"). Fork me on GitHub #wrap.homepage @@ -153,5 +158,6 @@ html(lang='en') Sponsor [Mongoose on OpenCollective](https://opencollective.com/mongoose) to get your company's logo above! p#footer Licensed under MIT. + script(src="docs/js/theme-toggle.js") script. document.body.className = 'load'; From 49200a18c9d9f7e2735c2597a768fd95bb256b43 Mon Sep 17 00:00:00 2001 From: White-Devil2839 Date: Wed, 26 Nov 2025 12:56:40 +0530 Subject: [PATCH 02/14] Fix: Requested changes --- docs/css/github.css | 123 ++++++++++++++++++++++++++++++++++++++++ docs/css/mongoose5.css | 8 +-- docs/css/style.css | 4 +- docs/js/theme-toggle.js | 67 ++++++++++++++-------- 4 files changed, 172 insertions(+), 30 deletions(-) diff --git a/docs/css/github.css b/docs/css/github.css index f4e134a0dd7..227688e7b51 100644 --- a/docs/css/github.css +++ b/docs/css/github.css @@ -169,6 +169,129 @@ github.com style (c) Vasily Polovnyov } /* Dark mode support for syntax highlighting */ +body.code-theme-dark code { + background-color: var(--code-bg, #2d2d2d); + color: var(--link-color, #4a9eff); +} + +body.code-theme-dark pre { + background-color: var(--code-bg, #2d2d2d); + border-color: var(--border-color, #444); + color: var(--code-text, #e0e0e0); +} + +body.code-theme-dark .hljs { + background: var(--code-bg, #2d2d2d); + color: var(--code-text, #e0e0e0); +} + +body.code-theme-dark .hljs-comment, +body.code-theme-dark .diff .hljs-header, +body.code-theme-dark .hljs-javadoc { + color: #6a9955; +} + +body.code-theme-dark .hljs-keyword, +body.code-theme-dark .css .rule .hljs-keyword, +body.code-theme-dark .hljs-winutils, +body.code-theme-dark .nginx .hljs-title, +body.code-theme-dark .hljs-subst, +body.code-theme-dark .hljs-request, +body.code-theme-dark .hljs-status { + color: #569cd6; + font-weight: bold; +} + +body.code-theme-dark .hljs-number, +body.code-theme-dark .hljs-hexcolor, +body.code-theme-dark .ruby .hljs-constant { + color: #b5cea8; +} + +body.code-theme-dark .hljs-string, +body.code-theme-dark .hljs-tag .hljs-value, +body.code-theme-dark .hljs-phpdoc, +body.code-theme-dark .hljs-dartdoc, +body.code-theme-dark .tex .hljs-formula { + color: #ce9178; +} + +body.code-theme-dark .hljs-title, +body.code-theme-dark .hljs-id, +body.code-theme-dark .scss .hljs-preprocessor { + color: #d7ba7d; + font-weight: bold; +} + +body.code-theme-dark .hljs-class .hljs-title, +body.code-theme-dark .hljs-type, +body.code-theme-dark .vhdl .hljs-literal, +body.code-theme-dark .tex .hljs-command { + color: #4ec9b0; + font-weight: bold; +} + +body.code-theme-dark .hljs-tag, +body.code-theme-dark .hljs-tag .hljs-title, +body.code-theme-dark .hljs-rules .hljs-property, +body.code-theme-dark .django .hljs-tag .hljs-keyword { + color: #569cd6; + font-weight: normal; +} + +body.code-theme-dark .hljs-attribute, +body.code-theme-dark .hljs-variable, +body.code-theme-dark .lisp .hljs-body { + color: #9cdcfe; +} + +body.code-theme-dark .hljs-regexp { + color: #d16969; +} + +body.code-theme-dark .hljs-symbol, +body.code-theme-dark .ruby .hljs-symbol .hljs-string, +body.code-theme-dark .lisp .hljs-keyword, +body.code-theme-dark .clojure .hljs-keyword, +body.code-theme-dark .scheme .hljs-keyword, +body.code-theme-dark .tex .hljs-special, +body.code-theme-dark .hljs-prompt { + color: #c586c0; +} + +body.code-theme-dark .hljs-built_in { + color: #4fc1ff; +} + +body.code-theme-dark .hljs-preprocessor, +body.code-theme-dark .hljs-pragma, +body.code-theme-dark .hljs-pi, +body.code-theme-dark .hljs-doctype, +body.code-theme-dark .hljs-shebang, +body.code-theme-dark .hljs-cdata { + color: #808080; + font-weight: bold; +} + +body.code-theme-dark .hljs-deletion { + background: #5a1d1d; + color: #f48771; +} + +body.code-theme-dark .hljs-addition { + background: #1e3a1e; + color: #b5cea8; +} + +body.code-theme-dark .diff .hljs-change { + background: #2d4d2d; + color: #4ec9b0; +} + +body.code-theme-dark .hljs-chunk { + color: #808080; +} + @media (prefers-color-scheme: dark) { code { background-color: var(--code-bg, #2d2d2d); diff --git a/docs/css/mongoose5.css b/docs/css/mongoose5.css index 141c6a7c89c..a6cd2e5c892 100644 --- a/docs/css/mongoose5.css +++ b/docs/css/mongoose5.css @@ -676,8 +676,8 @@ li.version ul.pure-menu-children { /* Theme Toggle Button */ #theme-toggle { position: fixed; - top: 10px; - left: 10px; + bottom: 20px; + right: 20px; z-index: 1000; background-color: var(--bg-secondary); border: 1px solid var(--border-color); @@ -751,7 +751,7 @@ li.version ul.pure-menu-children { /* On mobile, adjust position */ @media (max-width: 1160px) { #theme-toggle { - top: 5px; - left: 50px; + bottom: 15px; + right: 15px; } } diff --git a/docs/css/style.css b/docs/css/style.css index 095d187f27b..2f4a2ca6194 100644 --- a/docs/css/style.css +++ b/docs/css/style.css @@ -31,8 +31,8 @@ body[data-theme="light"] { /* Theme Toggle Button for Homepage */ #theme-toggle { position: fixed; - top: 10px; - left: 10px; + bottom: 20px; + right: 20px; z-index: 1000; background-color: rgba(255, 255, 255, 0.9); border: 1px solid #ddd; diff --git a/docs/js/theme-toggle.js b/docs/js/theme-toggle.js index df57c22c08e..44ae26f967d 100644 --- a/docs/js/theme-toggle.js +++ b/docs/js/theme-toggle.js @@ -1,43 +1,52 @@ (function() { 'use strict'; - // Get saved theme preference or default to system preference + const STORAGE_KEY = 'mongoose-theme'; + const CODE_THEME_CLASS = 'code-theme-dark'; + const supportsMatchMedia = typeof window !== 'undefined' && typeof window.matchMedia === 'function'; + const prefersDarkQuery = supportsMatchMedia ? window.matchMedia('(prefers-color-scheme: dark)') : null; + function getInitialTheme() { - const savedTheme = localStorage.getItem('mongoose-theme'); + const savedTheme = localStorage.getItem(STORAGE_KEY); if (savedTheme === 'light' || savedTheme === 'dark') { return savedTheme; } - // Default to system preference - return null; + return null; // Follow system preference + } + + function getEffectiveTheme(theme) { + if (theme === 'light' || theme === 'dark') { + return theme; + } + return prefersDarkQuery && prefersDarkQuery.matches ? 'dark' : 'light'; + } + + function syncCodeTheme(theme) { + const effectiveTheme = getEffectiveTheme(theme); + const isDark = effectiveTheme === 'dark'; + document.documentElement.classList.toggle(CODE_THEME_CLASS, isDark); + if (document.body) { + document.body.classList.toggle(CODE_THEME_CLASS, isDark); + } } - // Apply theme to document function applyTheme(theme) { if (theme === 'light' || theme === 'dark') { document.documentElement.setAttribute('data-theme', theme); - localStorage.setItem('mongoose-theme', theme); + localStorage.setItem(STORAGE_KEY, theme); } else { document.documentElement.removeAttribute('data-theme'); - localStorage.removeItem('mongoose-theme'); + localStorage.removeItem(STORAGE_KEY); } + syncCodeTheme(theme); updateThemeIcon(); } - // Update theme icon visibility function updateThemeIcon() { - // CSS handles the icon visibility, but we can ensure proper state - const theme = document.documentElement.getAttribute('data-theme'); - const lightIcon = document.getElementById('theme-icon-light'); // Sun icon - const darkIcon = document.getElementById('theme-icon-dark'); // Moon icon - - if (lightIcon && darkIcon) { - // In dark mode: show sun icon (to switch to light) - // In light mode: show moon icon (to switch to dark) - // CSS handles the actual visibility via opacity - } + // CSS handles the icon visibility. This function exists for future enhancements. + void document.documentElement.getAttribute('data-theme'); } - // Toggle between light and dark function toggleTheme() { const currentTheme = document.documentElement.getAttribute('data-theme'); if (currentTheme === 'dark') { @@ -45,24 +54,34 @@ } else if (currentTheme === 'light') { applyTheme(null); // Reset to system preference } else { - // Currently using system preference, switch to dark applyTheme('dark'); } } - // Initialize theme on page load + function handleSystemThemeChange() { + if (!localStorage.getItem(STORAGE_KEY)) { + syncCodeTheme(null); + } + } + function initTheme() { const initialTheme = getInitialTheme(); applyTheme(initialTheme); - - // Set up toggle button + const toggleBtn = document.getElementById('theme-toggle-btn'); if (toggleBtn) { toggleBtn.addEventListener('click', toggleTheme); } + + if (prefersDarkQuery) { + if (typeof prefersDarkQuery.addEventListener === 'function') { + prefersDarkQuery.addEventListener('change', handleSystemThemeChange); + } else if (typeof prefersDarkQuery.addListener === 'function') { + prefersDarkQuery.addListener(handleSystemThemeChange); + } + } } - // Run when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initTheme); } else { From 3f5e6e91f079b67c5abdde46c4a5f3dc0307ce4b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 2 Dec 2025 20:46:29 -0500 Subject: [PATCH 03/14] Update docs/api_split.pug Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- docs/api_split.pug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api_split.pug b/docs/api_split.pug index 78ff1b1a140..56b9d496596 100644 --- a/docs/api_split.pug +++ b/docs/api_split.pug @@ -1,7 +1,7 @@ extends layout append style - link(rel="stylesheet", href=`${versions.versionedPath}/docs/css/api.css?v=${Date.now()}`) + link(rel="stylesheet", href=`${versions.versionedPath}/docs/css/api.css?v=${versions.version}`) script(src=`${versions.versionedPath}/docs/js/api-bold-current-nav.js`) script(src=`${versions.versionedPath}/docs/js/convert-old-anchorid.js`) From dc35cfad22d68731fed5b8638d6554f662f03d34 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 2 Dec 2025 20:49:44 -0500 Subject: [PATCH 04/14] Update API CSS link in api_split.pug Removed version query parameter from API CSS link. --- docs/api_split.pug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api_split.pug b/docs/api_split.pug index 56b9d496596..2078d1b28ee 100644 --- a/docs/api_split.pug +++ b/docs/api_split.pug @@ -1,7 +1,7 @@ extends layout append style - link(rel="stylesheet", href=`${versions.versionedPath}/docs/css/api.css?v=${versions.version}`) + link(rel="stylesheet", href=`${versions.versionedPath}/docs/css/api.css`) script(src=`${versions.versionedPath}/docs/js/api-bold-current-nav.js`) script(src=`${versions.versionedPath}/docs/js/convert-old-anchorid.js`) From fddbf21f0c6222ddb2562f57886df89452d0a48b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 2 Dec 2025 20:54:56 -0500 Subject: [PATCH 05/14] Change logo text color and adjust theme toggle position --- docs/css/mongoose5.css | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/css/mongoose5.css b/docs/css/mongoose5.css index a6cd2e5c892..8cae0fda911 100644 --- a/docs/css/mongoose5.css +++ b/docs/css/mongoose5.css @@ -171,7 +171,7 @@ h4 a:focus-visible { } .logo-text { - color: var(--link-color); + color: #800; font-size: 20pt; position: relative; top: 0px; @@ -676,7 +676,7 @@ li.version ul.pure-menu-children { /* Theme Toggle Button */ #theme-toggle { position: fixed; - bottom: 20px; + top: 20px; right: 20px; z-index: 1000; background-color: var(--bg-secondary); @@ -751,6 +751,7 @@ li.version ul.pure-menu-children { /* On mobile, adjust position */ @media (max-width: 1160px) { #theme-toggle { + top: auto; bottom: 15px; right: 15px; } From 8af7b0b03473eef390aa23253df9c4076da1b80c Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 2 Dec 2025 20:57:54 -0500 Subject: [PATCH 06/14] Remove cache-busting query parameters from CSS links --- index.pug | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.pug b/index.pug index f219d428acd..b0fd5bffcfa 100644 --- a/index.pug +++ b/index.pug @@ -5,9 +5,9 @@ html(lang='en') meta(name="viewport", content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") title Mongoose ODM v#{package.version} link(href="//fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700", rel="stylesheet", type="text/css") - link(href="docs/css/mongoose5.css?v=" + Date.now(), rel="stylesheet") - link(href="docs/css/style.css?v=" + Date.now(), rel="stylesheet") - link(href="docs/css/github.css?v=" + Date.now(), rel="stylesheet") + link(href="docs/css/mongoose5.css", rel="stylesheet") + link(href="docs/css/style.css", rel="stylesheet") + link(href="docs/css/github.css", rel="stylesheet") link(href="docs/css/carbonads.css", rel="stylesheet") include ./docs/includes/favicon From 72150d346b67c3da8a9361bce58d2dcf608c1962 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 2 Dec 2025 21:04:01 -0500 Subject: [PATCH 07/14] Adjust theme toggle button position --- docs/css/style.css | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/css/style.css b/docs/css/style.css index 2f4a2ca6194..2e404c97b0d 100644 --- a/docs/css/style.css +++ b/docs/css/style.css @@ -31,6 +31,7 @@ body[data-theme="light"] { /* Theme Toggle Button for Homepage */ #theme-toggle { position: fixed; + top: auto; bottom: 20px; right: 20px; z-index: 1000; From 17d3adfef1f5e1a683a18de399ef4bf771002803 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 4 Dec 2025 15:47:42 -0500 Subject: [PATCH 08/14] Refactor theme toggle functions for improved clarity --- docs/js/theme-toggle.js | 81 ++++++----------------------------------- 1 file changed, 12 insertions(+), 69 deletions(-) diff --git a/docs/js/theme-toggle.js b/docs/js/theme-toggle.js index 44ae26f967d..3fc019d4227 100644 --- a/docs/js/theme-toggle.js +++ b/docs/js/theme-toggle.js @@ -6,86 +6,29 @@ const supportsMatchMedia = typeof window !== 'undefined' && typeof window.matchMedia === 'function'; const prefersDarkQuery = supportsMatchMedia ? window.matchMedia('(prefers-color-scheme: dark)') : null; - function getInitialTheme() { - const savedTheme = localStorage.getItem(STORAGE_KEY); - if (savedTheme === 'light' || savedTheme === 'dark') { - return savedTheme; - } - return null; // Follow system preference - } - - function getEffectiveTheme(theme) { - if (theme === 'light' || theme === 'dark') { - return theme; - } - return prefersDarkQuery && prefersDarkQuery.matches ? 'dark' : 'light'; - } - - function syncCodeTheme(theme) { - const effectiveTheme = getEffectiveTheme(theme); - const isDark = effectiveTheme === 'dark'; - document.documentElement.classList.toggle(CODE_THEME_CLASS, isDark); - if (document.body) { - document.body.classList.toggle(CODE_THEME_CLASS, isDark); - } - } - - function applyTheme(theme) { - if (theme === 'light' || theme === 'dark') { - document.documentElement.setAttribute('data-theme', theme); - localStorage.setItem(STORAGE_KEY, theme); - } else { - document.documentElement.removeAttribute('data-theme'); - localStorage.removeItem(STORAGE_KEY); - } - syncCodeTheme(theme); - updateThemeIcon(); - } - - function updateThemeIcon() { - // CSS handles the icon visibility. This function exists for future enhancements. - void document.documentElement.getAttribute('data-theme'); - } - function toggleTheme() { const currentTheme = document.documentElement.getAttribute('data-theme'); if (currentTheme === 'dark') { applyTheme('light'); - } else if (currentTheme === 'light') { - applyTheme(null); // Reset to system preference } else { applyTheme('dark'); } } - function handleSystemThemeChange() { - if (!localStorage.getItem(STORAGE_KEY)) { - syncCodeTheme(null); - } - } - - function initTheme() { - const initialTheme = getInitialTheme(); - applyTheme(initialTheme); - - const toggleBtn = document.getElementById('theme-toggle-btn'); - if (toggleBtn) { - toggleBtn.addEventListener('click', toggleTheme); + function applyTheme(theme, skipSetStorage) { + document.documentElement.setAttribute('data-theme', theme); + if (!skipSetStorage) { + localStorage.setItem(STORAGE_KEY, theme); } - - if (prefersDarkQuery) { - if (typeof prefersDarkQuery.addEventListener === 'function') { - prefersDarkQuery.addEventListener('change', handleSystemThemeChange); - } else if (typeof prefersDarkQuery.addListener === 'function') { - prefersDarkQuery.addListener(handleSystemThemeChange); - } + const isDark = theme === 'dark'; + document.documentElement.classList.toggle(CODE_THEME_CLASS, isDark); + if (document.body) { + document.body.classList.toggle(CODE_THEME_CLASS, isDark); } } - if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', initTheme); - } else { - initTheme(); - } + const theme = localStorage.getItem(STORAGE_KEY) || (prefersDarkQuery?.matches ? 'dark' : 'light'); + applyTheme(theme, true); + const toggleBtn = document.getElementById('theme-toggle-btn'); + toggleBtn.addEventListener('click', toggleTheme); })(); - From 8144b3f88e2804a41233d78f063d3954286e66d2 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 4 Dec 2025 16:21:38 -0500 Subject: [PATCH 09/14] Refactor theme styles for dark and light modes --- docs/css/style.css | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/docs/css/style.css b/docs/css/style.css index 2e404c97b0d..ae06f764eaa 100644 --- a/docs/css/style.css +++ b/docs/css/style.css @@ -18,12 +18,12 @@ body { } /* Manual theme overrides */ -body[data-theme="dark"] { +[data-theme="dark"] { background-color: var(--bg-primary, #1a1a1a); color: var(--text-secondary, #c0c0c0); } -body[data-theme="light"] { +[data-theme="light"] { background-color: var(--bg-primary, #ffffff); color: var(--text-secondary, #333); } @@ -31,7 +31,6 @@ body[data-theme="light"] { /* Theme Toggle Button for Homepage */ #theme-toggle { position: fixed; - top: auto; bottom: 20px; right: 20px; z-index: 1000; @@ -42,7 +41,7 @@ body[data-theme="light"] { transition: background-color 0.3s ease, border-color 0.3s ease; } -body[data-theme="dark"] #theme-toggle { +[data-theme="dark"] #theme-toggle { background-color: rgba(26, 26, 26, 0.9); border-color: #444; } @@ -186,15 +185,13 @@ pre code { } /* Dark mode for homepage code blocks */ -@media (prefers-color-scheme: dark) { - pre { - background: var(--code-bg, #2d2d2d); - border-color: var(--border-color, #444); - } - code { - color: var(--code-text, #e0e0e0); - background-color: var(--code-bg, #2d2d2d); - } +[data-theme="dark"] pre { + background: var(--code-bg, #2d2d2d); + border-color: var(--border-color, #444); +} +[data-theme="dark"] code { + color: var(--code-text, #e0e0e0); + background-color: var(--code-bg, #2d2d2d); } #header { text-align: center; @@ -221,6 +218,7 @@ h2 a { font-size: 146px; font-weight: 100; text-indent: -23px; + color: #800; } .load #header .mongoose { letter-spacing: -14px; @@ -232,6 +230,10 @@ h2 a { text-align: center; margin: 7px 0; } +[data-theme="dark"] .tagline { + color: #f8f8f8; + text-shadow: 1px 1px #222; +} .blurb { text-align: center; font-style: oblique; @@ -254,7 +256,6 @@ h2 a { #links li { display: inline-block; margin: 0 15px; - background-color: #FEFEFE; } #links a { background: #444; From 5bbe4adfd103b5a843ec4c9616f2b1d9ede94a7f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 4 Dec 2025 16:22:37 -0500 Subject: [PATCH 10/14] Refactor dark mode styles for syntax highlighting --- docs/css/github.css | 233 ++++++++++---------------------------------- 1 file changed, 54 insertions(+), 179 deletions(-) diff --git a/docs/css/github.css b/docs/css/github.css index 227688e7b51..f7aa548e0b7 100644 --- a/docs/css/github.css +++ b/docs/css/github.css @@ -169,254 +169,129 @@ github.com style (c) Vasily Polovnyov } /* Dark mode support for syntax highlighting */ -body.code-theme-dark code { +.code-theme-dark code { background-color: var(--code-bg, #2d2d2d); color: var(--link-color, #4a9eff); } -body.code-theme-dark pre { +.code-theme-dark pre { background-color: var(--code-bg, #2d2d2d); border-color: var(--border-color, #444); color: var(--code-text, #e0e0e0); } -body.code-theme-dark .hljs { +.code-theme-dark .hljs { background: var(--code-bg, #2d2d2d); color: var(--code-text, #e0e0e0); } -body.code-theme-dark .hljs-comment, -body.code-theme-dark .diff .hljs-header, -body.code-theme-dark .hljs-javadoc { +.code-theme-dark .hljs-comment, +.code-theme-dark .diff .hljs-header, +.code-theme-dark .hljs-javadoc { color: #6a9955; } -body.code-theme-dark .hljs-keyword, -body.code-theme-dark .css .rule .hljs-keyword, -body.code-theme-dark .hljs-winutils, -body.code-theme-dark .nginx .hljs-title, -body.code-theme-dark .hljs-subst, -body.code-theme-dark .hljs-request, -body.code-theme-dark .hljs-status { +.code-theme-dark .hljs-keyword, +.code-theme-dark .css .rule .hljs-keyword, +.code-theme-dark .hljs-winutils, +.code-theme-dark .nginx .hljs-title, +.code-theme-dark .hljs-subst, +.code-theme-dark .hljs-request, +.code-theme-dark .hljs-status { color: #569cd6; font-weight: bold; } -body.code-theme-dark .hljs-number, -body.code-theme-dark .hljs-hexcolor, -body.code-theme-dark .ruby .hljs-constant { +.code-theme-dark .hljs-number, +.code-theme-dark .hljs-hexcolor, +.code-theme-dark .ruby .hljs-constant { color: #b5cea8; } -body.code-theme-dark .hljs-string, -body.code-theme-dark .hljs-tag .hljs-value, -body.code-theme-dark .hljs-phpdoc, -body.code-theme-dark .hljs-dartdoc, -body.code-theme-dark .tex .hljs-formula { +.code-theme-dark .hljs-string, +.code-theme-dark .hljs-tag .hljs-value, +.code-theme-dark .hljs-phpdoc, +.code-theme-dark .hljs-dartdoc, +.code-theme-dark .tex .hljs-formula { color: #ce9178; } -body.code-theme-dark .hljs-title, -body.code-theme-dark .hljs-id, -body.code-theme-dark .scss .hljs-preprocessor { +.code-theme-dark .hljs-title, +.code-theme-dark .hljs-id, +.code-theme-dark .scss .hljs-preprocessor { color: #d7ba7d; font-weight: bold; } -body.code-theme-dark .hljs-class .hljs-title, -body.code-theme-dark .hljs-type, -body.code-theme-dark .vhdl .hljs-literal, -body.code-theme-dark .tex .hljs-command { +.code-theme-dark .hljs-class .hljs-title, +.code-theme-dark .hljs-type, +.code-theme-dark .vhdl .hljs-literal, +.code-theme-dark .tex .hljs-command { color: #4ec9b0; font-weight: bold; } -body.code-theme-dark .hljs-tag, -body.code-theme-dark .hljs-tag .hljs-title, -body.code-theme-dark .hljs-rules .hljs-property, -body.code-theme-dark .django .hljs-tag .hljs-keyword { +.code-theme-dark .hljs-tag, +.code-theme-dark .hljs-tag .hljs-title, +.code-theme-dark .hljs-rules .hljs-property, +.code-theme-dark .django .hljs-tag .hljs-keyword { color: #569cd6; font-weight: normal; } -body.code-theme-dark .hljs-attribute, -body.code-theme-dark .hljs-variable, -body.code-theme-dark .lisp .hljs-body { +.code-theme-dark .hljs-attribute, +.code-theme-dark .hljs-variable, +.code-theme-dark .lisp .hljs-body { color: #9cdcfe; } -body.code-theme-dark .hljs-regexp { +.code-theme-dark .hljs-regexp { color: #d16969; } -body.code-theme-dark .hljs-symbol, -body.code-theme-dark .ruby .hljs-symbol .hljs-string, -body.code-theme-dark .lisp .hljs-keyword, -body.code-theme-dark .clojure .hljs-keyword, -body.code-theme-dark .scheme .hljs-keyword, -body.code-theme-dark .tex .hljs-special, -body.code-theme-dark .hljs-prompt { +.code-theme-dark .hljs-symbol, +.code-theme-dark .ruby .hljs-symbol .hljs-string, +.code-theme-dark .lisp .hljs-keyword, +.code-theme-dark .clojure .hljs-keyword, +.code-theme-dark .scheme .hljs-keyword, +.code-theme-dark .tex .hljs-special, +.code-theme-dark .hljs-prompt { color: #c586c0; } -body.code-theme-dark .hljs-built_in { +.code-theme-dark .hljs-built_in { color: #4fc1ff; } -body.code-theme-dark .hljs-preprocessor, -body.code-theme-dark .hljs-pragma, -body.code-theme-dark .hljs-pi, -body.code-theme-dark .hljs-doctype, -body.code-theme-dark .hljs-shebang, -body.code-theme-dark .hljs-cdata { +.code-theme-dark .hljs-preprocessor, +.code-theme-dark .hljs-pragma, +.code-theme-dark .hljs-pi, +.code-theme-dark .hljs-doctype, +.code-theme-dark .hljs-shebang, +.code-theme-dark .hljs-cdata { color: #808080; font-weight: bold; } -body.code-theme-dark .hljs-deletion { +.code-theme-dark .hljs-deletion { background: #5a1d1d; color: #f48771; } -body.code-theme-dark .hljs-addition { +.code-theme-dark .hljs-addition { background: #1e3a1e; color: #b5cea8; } -body.code-theme-dark .diff .hljs-change { +.code-theme-dark .diff .hljs-change { background: #2d4d2d; color: #4ec9b0; } -body.code-theme-dark .hljs-chunk { +.code-theme-dark .hljs-chunk { color: #808080; } -@media (prefers-color-scheme: dark) { - code { - background-color: var(--code-bg, #2d2d2d); - color: var(--link-color, #4a9eff); - } - - pre { - background-color: var(--code-bg, #2d2d2d); - border-color: var(--border-color, #444); - color: var(--code-text, #e0e0e0); - } - - .hljs { - background: var(--code-bg, #2d2d2d); - color: var(--code-text, #e0e0e0); - } - - .hljs-comment, - .diff .hljs-header, - .hljs-javadoc { - color: #6a9955; - } - - .hljs-keyword, - .css .rule .hljs-keyword, - .hljs-winutils, - .nginx .hljs-title, - .hljs-subst, - .hljs-request, - .hljs-status { - color: #569cd6; - font-weight: bold; - } - - .hljs-number, - .hljs-hexcolor, - .ruby .hljs-constant { - color: #b5cea8; - } - - .hljs-string, - .hljs-tag .hljs-value, - .hljs-phpdoc, - .hljs-dartdoc, - .tex .hljs-formula { - color: #ce9178; - } - - .hljs-title, - .hljs-id, - .scss .hljs-preprocessor { - color: #d7ba7d; - font-weight: bold; - } - - .hljs-class .hljs-title, - .hljs-type, - .vhdl .hljs-literal, - .tex .hljs-command { - color: #4ec9b0; - font-weight: bold; - } - - .hljs-tag, - .hljs-tag .hljs-title, - .hljs-rules .hljs-property, - .django .hljs-tag .hljs-keyword { - color: #569cd6; - font-weight: normal; - } - - .hljs-attribute, - .hljs-variable, - .lisp .hljs-body { - color: #9cdcfe; - } - - .hljs-regexp { - color: #d16969; - } - - .hljs-symbol, - .ruby .hljs-symbol .hljs-string, - .lisp .hljs-keyword, - .clojure .hljs-keyword, - .scheme .hljs-keyword, - .tex .hljs-special, - .hljs-prompt { - color: #c586c0; - } - - .hljs-built_in { - color: #4fc1ff; - } - - .hljs-preprocessor, - .hljs-pragma, - .hljs-pi, - .hljs-doctype, - .hljs-shebang, - .hljs-cdata { - color: #808080; - font-weight: bold; - } - - .hljs-deletion { - background: #5a1d1d; - color: #f48771; - } - - .hljs-addition { - background: #1e3a1e; - color: #b5cea8; - } - - .diff .hljs-change { - background: #2d4d2d; - color: #4ec9b0; - } - - .hljs-chunk { - color: #808080; - } -} - /* Accessibility: Ensure sufficient contrast for code */ code, pre, From 032ac6933d8096b4e11cfe9bdfcf3ff340361f45 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 4 Dec 2025 16:23:06 -0500 Subject: [PATCH 11/14] Refactor theme toggle logic for body class --- docs/js/theme-toggle.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/js/theme-toggle.js b/docs/js/theme-toggle.js index 3fc019d4227..d773edb32ac 100644 --- a/docs/js/theme-toggle.js +++ b/docs/js/theme-toggle.js @@ -22,9 +22,7 @@ } const isDark = theme === 'dark'; document.documentElement.classList.toggle(CODE_THEME_CLASS, isDark); - if (document.body) { - document.body.classList.toggle(CODE_THEME_CLASS, isDark); - } + document.body.classList.toggle(CODE_THEME_CLASS, isDark); } const theme = localStorage.getItem(STORAGE_KEY) || (prefersDarkQuery?.matches ? 'dark' : 'light'); From 68757dbf01762c0623b9a3117b2e0985e6396e10 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 4 Dec 2025 17:15:27 -0500 Subject: [PATCH 12/14] Update docs/css/github.css Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- docs/css/github.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/css/github.css b/docs/css/github.css index f7aa548e0b7..d1d69d6f91e 100644 --- a/docs/css/github.css +++ b/docs/css/github.css @@ -33,7 +33,7 @@ pre { transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease; } -/* Improve code block copy functionality */ +/* Enable absolute positioning for copy button and improve hover effect */ pre { position: relative; } From 3398f0c647d72ca79817ab7ac9df39ac64ab7c6e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 4 Dec 2025 17:16:05 -0500 Subject: [PATCH 13/14] Update docs/css/mongoose5.css Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- docs/css/mongoose5.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/css/mongoose5.css b/docs/css/mongoose5.css index 8cae0fda911..71f26843bf7 100644 --- a/docs/css/mongoose5.css +++ b/docs/css/mongoose5.css @@ -13,8 +13,8 @@ --code-bg: #f5f5f5; --code-text: #333; --menu-bg: #eee; - --menu-hover: rgba(0,0,0, 0.1); - --menu-selected: rgba(0,0,0, 0.15); + --menu-hover: rgba(0, 0, 0, 0.1); + --menu-selected: rgba(0, 0, 0, 0.15); --shadow: rgba(0, 0, 0, 0.1); --focus-ring: #0971B2; --focus-ring-width: 3px; From e2464af4fdbeb183108e9b04a72d7707334dc01b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 4 Dec 2025 17:16:47 -0500 Subject: [PATCH 14/14] Update docs/js/theme-toggle.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- docs/js/theme-toggle.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/js/theme-toggle.js b/docs/js/theme-toggle.js index d773edb32ac..1fb347e0458 100644 --- a/docs/js/theme-toggle.js +++ b/docs/js/theme-toggle.js @@ -18,7 +18,11 @@ function applyTheme(theme, skipSetStorage) { document.documentElement.setAttribute('data-theme', theme); if (!skipSetStorage) { - localStorage.setItem(STORAGE_KEY, theme); + try { + localStorage.setItem(STORAGE_KEY, theme); + } catch (e) { + // Silently fail - theme will still work for current session + } } const isDark = theme === 'dark'; document.documentElement.classList.toggle(CODE_THEME_CLASS, isDark);