From 3cba22a25904d00221d1f72e1821e445e6905f01 Mon Sep 17 00:00:00 2001 From: apiraino Date: Wed, 24 Jul 2024 17:45:25 +0200 Subject: [PATCH 1/4] Replace CSS vars with HTML vars --- src/styles/app.scss | 56 ++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/src/styles/app.scss b/src/styles/app.scss index bd59032be..293e40613 100644 --- a/src/styles/app.scss +++ b/src/styles/app.scss @@ -3,11 +3,16 @@ $body-font: 'Fira Sans', Helvetica, Arial, sans-serif; $header-font: 'Alfa Slab One', serif; -$gray: #2a3439; -$red: #a72145; -$green: #0b7261; -$purple: #2e2459; -$yellow: #ffc832; +// Default light theme +:root { + --gray: #2a3439; + --red: #a72145; + --yellow: #ffc832; + --code-bg-color: rgba(42, 52, 57, 0.05); + --code-border-color: rgba(42, 52, 57, 0.25); + --blockquote-bg-color: rgb(247, 249, 249); + --blockquote-left-border-color: rgb(195, 205, 210); +} html { font-size: 62.5% @@ -35,8 +40,8 @@ body { blockquote { font-style: italic; position: relative; - background-color: lighten($gray, 78%); - border-left: 8px solid lighten($gray, 60%); + background-color: var(--blockquote-bg-color); + border-left: 8px solid var(--blockquote-left-border-color); border-radius: 5px; margin: 0; margin-bottom: 2rem; @@ -110,7 +115,7 @@ ul.nav, ul.nav li { } .nav a { - color: $gray; + color: var(--gray); } div.brand { @@ -141,28 +146,28 @@ div.brand { .white { color: black; .highlight { - background-color: $yellow; + background-color: var(--yellow); } a { - color: $gray; + color: var(--gray); text-decoration: underline; } .button.button-secondary { - background-color: $yellow; - border: 1px solid $yellow; - color: $gray; + background-color: var(--yellow); + color: var(--gray); + border: 1px solid var(--yellow); text-decoration: none; display: block; overflow: hidden; text-overflow: ellipsis; &:hover, &:focus { - border-color: $gray; + border-color: var(--gray); } } code { color: black; - background-color: rgba($gray, 0.05); - border: 1px solid rgba($gray, 0.25); + background-color: var(--code-bg-color); + border: 1px solid var(--code-border-color); } a.anchor::before { @@ -173,7 +178,7 @@ div.brand { margin-left: -1em; text-decoration: none; opacity: 0.7; - color: $gray; + color: var(--gray); font-weight: normal; } :hover > a.anchor::before { @@ -194,18 +199,18 @@ ul { } .posts { - background-color: $gray; + background-color: var(--gray); color: white; .highlight { - background-color: $red; + background-color: var(--red); } a { color: white; text-decoration: underline; } .button.button-secondary { - background-color: $red; - border: 1px solid $red; + background-color: var(--red); + border: 1px solid var(--red); color: white; text-decoration: none; display: block; @@ -230,7 +235,7 @@ table.post-list a:hover { } .publish-date-author { - color: $gray; + color: var(--gray); margin: -60px 0 60px 0; } @@ -245,11 +250,11 @@ footer { } a { - color: $yellow; + color: var(--yellow); text-decoration: none; &:hover { - color: $yellow; + color: var(--yellow); text-decoration: underline; } } @@ -281,7 +286,7 @@ h3, .post h2, header h2 { h2 { font-size: 2em; } - + h3 { display: block; } @@ -323,4 +328,3 @@ header h1 { border-top-left-radius: 0; } } - From ee2f8cfa1e19a53a035ededbdaf54e4ad09b8f24 Mon Sep 17 00:00:00 2001 From: apiraino Date: Mon, 29 Jul 2024 17:18:59 +0200 Subject: [PATCH 2/4] Add dark mode --- src/styles/app.scss | 55 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/src/styles/app.scss b/src/styles/app.scss index 293e40613..b7e48bd33 100644 --- a/src/styles/app.scss +++ b/src/styles/app.scss @@ -8,14 +8,46 @@ $header-font: 'Alfa Slab One', serif; --gray: #2a3439; --red: #a72145; --yellow: #ffc832; + --code-color: black; --code-bg-color: rgba(42, 52, 57, 0.05); --code-border-color: rgba(42, 52, 57, 0.25); + --blockquote-color: black; --blockquote-bg-color: rgb(247, 249, 249); --blockquote-left-border-color: rgb(195, 205, 210); + --body-background-color: white; + --body-foreground-color: white; + --body-color: rgb(34,34,34); + --div-brand-a-color: black; + --white-elem-color: black; + --white-a: #2a3439; + --nav-links-a: #2a3439; + --publish-date-author: #2a3439; + --section-header-h2-color: black; +} + +// Dark theme +@media (prefers-color-scheme: dark) { + :root { + --code-color: white; + --code-bg-color: rgba(213, 203, 198, 0.05); + --code-border-color: rgba(213, 203, 198, 0.25); + --blockquote-color: rgb(195, 205, 210); + --blockquote-bg-color: rgba(213, 203, 198, 0.05); + --blockquote-left-border-color: rgb(195, 205, 210); + --body-background-color: #181a1b; + --body-foreground-color: #e8e6e3; + --body-color: white; + --div-brand-a-color: white; + --white-elem-color: white; + --white-elem-a: #d5cbc6; + --nav-links-a: #d5cbc6; + --publish-date-author: #d5cbc6; + --section-header-h2-color: white; + } } html { - font-size: 62.5% + font-size: 62.5%; } @media screen and (min-width: 30em) { @@ -26,14 +58,15 @@ html { body { font-family: $body-font; - background-color: white; + background-color: var(--body-background-color); + color: var(--body-color); /* Ensure the footer is always at the bottom of the screen */ min-height: 100vh; display: flex; flex-direction: column; & > #main-content { - flex: 1; + flex: 1; } } @@ -85,6 +118,7 @@ section { margin: 0; padding: 0; letter-spacing: 1px; + color: var(--section-header-h2-color); } } } @@ -116,6 +150,7 @@ ul.nav, ul.nav li { .nav a { color: var(--gray); + color: var(--nav-links-a); } div.brand { @@ -128,7 +163,7 @@ div.brand { margin-top: $v-top; & a { - color: black; + color: var(--div-brand-a-color); text-decoration: none; } @@ -144,12 +179,12 @@ div.brand { } .white { - color: black; + color: var(--white-elem-color); .highlight { background-color: var(--yellow); } a { - color: var(--gray); + color: var(--white-elem-a); text-decoration: underline; } .button.button-secondary { @@ -165,7 +200,7 @@ div.brand { } } code { - color: black; + color: var(--code-color); background-color: var(--code-bg-color); border: 1px solid var(--code-border-color); } @@ -200,12 +235,12 @@ ul { .posts { background-color: var(--gray); - color: white; + color: var(--body-foreground-color); .highlight { background-color: var(--red); } a { - color: white; + color: var(--body-foreground-color); text-decoration: underline; } .button.button-secondary { @@ -235,7 +270,7 @@ table.post-list a:hover { } .publish-date-author { - color: var(--gray); + color: var(--publish-date-author); margin: -60px 0 60px 0; } From b2b716f04fb874632576eb1ad1c4007fb13f90e0 Mon Sep 17 00:00:00 2001 From: apiraino Date: Fri, 9 Aug 2024 15:35:57 +0200 Subject: [PATCH 3/4] Add theme selector --- .gitignore | 1 + src/lib.rs | 1 + src/styles/app.scss | 93 +++++++++++++++++++++++++++------- src/styles/noscript.scss | 53 +++++++++++++++++++ static/scripts/theme-switch.js | 63 +++++++++++++++++++++++ templates/footer.hbs | 1 + templates/headers.hbs | 21 +++++--- templates/nav.hbs | 6 +++ 8 files changed, 212 insertions(+), 27 deletions(-) create mode 100644 src/styles/noscript.scss create mode 100644 static/scripts/theme-switch.js diff --git a/.gitignore b/.gitignore index 0691a5444..c12003316 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ site static/styles/vendor.css static/styles/app.css static/styles/fonts.css +static/styles/noscript.css diff --git a/src/lib.rs b/src/lib.rs index 6823f1193..38e0cfe05 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -88,6 +88,7 @@ impl<'a> Generator<'a> { self.render_blog(blog)?; } self.compile_sass("app")?; + self.compile_sass("noscript")?; self.compile_sass("fonts")?; self.concat_vendor_css(vec!["skeleton", "tachyons"])?; self.copy_static_files()?; diff --git a/src/styles/app.scss b/src/styles/app.scss index b7e48bd33..227e7821b 100644 --- a/src/styles/app.scss +++ b/src/styles/app.scss @@ -3,8 +3,10 @@ $body-font: 'Fira Sans', Helvetica, Arial, sans-serif; $header-font: 'Alfa Slab One', serif; +// Switching theme will only work if JavaScript is enabled as well + // Default light theme -:root { +:root, :root:not([data-theme]) { --gray: #2a3439; --red: #a72145; --yellow: #ffc832; @@ -23,27 +25,38 @@ $header-font: 'Alfa Slab One', serif; --nav-links-a: #2a3439; --publish-date-author: #2a3439; --section-header-h2-color: black; + --theme-icon: #43484d; + --theme-popup-border: #43484d; + --theme-popup-bg: white; + --theme-hover: #cacaca; + --theme-choice-color: black; } // Dark theme -@media (prefers-color-scheme: dark) { - :root { - --code-color: white; - --code-bg-color: rgba(213, 203, 198, 0.05); - --code-border-color: rgba(213, 203, 198, 0.25); - --blockquote-color: rgb(195, 205, 210); - --blockquote-bg-color: rgba(213, 203, 198, 0.05); - --blockquote-left-border-color: rgb(195, 205, 210); - --body-background-color: #181a1b; - --body-foreground-color: #e8e6e3; - --body-color: white; - --div-brand-a-color: white; - --white-elem-color: white; - --white-elem-a: #d5cbc6; - --nav-links-a: #d5cbc6; - --publish-date-author: #d5cbc6; - --section-header-h2-color: white; - } +:root[data-theme='dark'] { + --gray: #2a3439; + --red: #a72145; + --yellow: #ffc832; + --code-color: white; + --code-bg-color: rgba(213, 203, 198, 0.05); + --code-border-color: rgba(213, 203, 198, 0.25); + --blockquote-color: rgb(195, 205, 210); + --blockquote-bg-color: rgba(213, 203, 198, 0.05); + --blockquote-left-border-color: rgb(195, 205, 210); + --body-background-color: #181a1b; + --body-foreground-color: #e8e6e3; + --body-color: white; + --div-brand-a-color: white; + --white-elem-color: white; + --white-elem-a: #d5cbc6; + --nav-links-a: #d5cbc6; + --publish-date-author: #d5cbc6; + --section-header-h2-color: white; + --theme-icon: #43484d; + --theme-popup-border: #43484d; + --theme-popup-bg: #141617; + --theme-hover: #474c51; + --theme-choice-color: #d5cbc6; } html { @@ -363,3 +376,45 @@ header h1 { border-top-left-radius: 0; } } + +// Theme switch popup +// theme selector visible only if JavaScript is available + +.theme-icon { + display: none; + line-height: 2em; + border: 2px solid var(--theme-icon); + border-radius: 5px; + padding: 0px 5px; + color: var(--theme-choice-color); + &:hover { + color: var(--theme-choice-color); + } +} + +#theme-choice { + display: none; + border: 2px solid var(--theme-popup-border); + border-radius: 5px; + color: var(--theme-choice-color); + background: var(--theme-popup-bg); + position: absolute; + list-style: none; + font-weight: 400; + padding: 0px; + // counterbalance vendored skeleton.css + margin: 0.2em -0.5em; +} + +.theme-item { + padding: 0px 5px; +} + +#theme-choice.showThemeDropdown { + display: block; + z-index: 1; +} + +li.theme-item:hover { + background-color: var(--theme-hover); +} diff --git a/src/styles/noscript.scss b/src/styles/noscript.scss new file mode 100644 index 000000000..ced45fe5e --- /dev/null +++ b/src/styles/noscript.scss @@ -0,0 +1,53 @@ +// This stylesheet is used when the user agent has no JavaScript capabilities (or has it disabled) +// Sets dark theme according to user agent preferences + +// Default light theme +:root, :root:not([data-theme]) { + --gray: #2a3439; + --red: #a72145; + --yellow: #ffc832; + --code-color: black; + --code-bg-color: rgba(42, 52, 57, 0.05); + --code-border-color: rgba(42, 52, 57, 0.25); + --blockquote-color: black; + --blockquote-bg-color: rgb(247, 249, 249); + --blockquote-left-border-color: rgb(195, 205, 210); + --body-background-color: white; + --body-foreground-color: white; + --body-color: rgb(34,34,34); + --div-brand-a-color: black; + --white-elem-color: black; + --white-a: #2a3439; + --nav-links-a: #2a3439; + --publish-date-author: #2a3439; + --section-header-h2-color: black; +} + +// Dark theme (probed from user prefs) +@media (prefers-color-scheme: dark) { + :root, :root:not([data-theme]) { + --gray: #2a3439; + --red: #a72145; + --yellow: #ffc832; + --code-color: white; + --code-bg-color: rgba(213, 203, 198, 0.05); + --code-border-color: rgba(213, 203, 198, 0.25); + --blockquote-color: rgb(195, 205, 210); + --blockquote-bg-color: rgba(213, 203, 198, 0.05); + --blockquote-left-border-color: rgb(195, 205, 210); + --body-background-color: #181a1b; + --body-foreground-color: #e8e6e3; + --body-color: white; + --div-brand-a-color: white; + --white-elem-color: white; + --white-elem-a: #d5cbc6; + --nav-links-a: #d5cbc6; + --publish-date-author: #d5cbc6; + --section-header-h2-color: white; + } +} + +// Don't show the theme selector button when JavaScript is disabled +#theme-icon { + display: none !important; +} diff --git a/static/scripts/theme-switch.js b/static/scripts/theme-switch.js new file mode 100644 index 000000000..804e72b58 --- /dev/null +++ b/static/scripts/theme-switch.js @@ -0,0 +1,63 @@ +"use strict"; + +function changeThemeTo(val) { + document.documentElement.setAttribute("data-theme", val); + // save theme prefs in the browser + if (storageAvailable("localStorage")) { + localStorage.setItem("blog-rust-lang-org-theme", val); + } + // the theme dropdown will close itself when returning to the dropdown() caller +} + +function dropdown () { + document.getElementById("theme-choice").classList.toggle("showThemeDropdown"); +} + +// courtesy MDN +function storageAvailable(type) { + let storage; + try { + storage = window[type]; + const x = "__storage_test__"; + storage.setItem(x, x); + storage.removeItem(x); + return true; + } catch (e) { + return ( + e instanceof DOMException && + e.name === "QuotaExceededError" && + // acknowledge QuotaExceededError only if there's something already stored + storage && + storage.length !== 0 + ); + } +} + +function handleBlur(event) { + const parent = document.getElementById("theme-choice"); + if (!parent.contains(document.activeElement) && + !parent.contains(event.relatedTarget) && + parent.classList.contains("showThemeDropdown") + ) { + console.debug('Closing the dropdown'); + parent.classList.remove("showThemeDropdown"); + } +} + +// close the theme dropdown if clicking somewhere else +document.querySelector('.theme-icon').onblur = handleBlur; + +// Check for saved user preference on load, else check and save user agent prefs +let savedTheme = null; +if (storageAvailable("localStorage")) { + savedTheme = localStorage.getItem("blog-rust-lang-org-theme"); +} +if (savedTheme) { + document.documentElement.setAttribute("data-theme", savedTheme); +} else if (window.matchMedia("(prefers-color-scheme: dark)").matches) { + document.documentElement.setAttribute("data-theme", "dark"); + localStorage.setItem("blog-rust-lang-org-theme", "dark"); +} + +// show the theme selector only if JavaScript is enabled/available +document.querySelector('.theme-icon').style.display = 'block'; diff --git a/templates/footer.hbs b/templates/footer.hbs index 30899b465..b089d6b1b 100644 --- a/templates/footer.hbs +++ b/templates/footer.hbs @@ -44,3 +44,4 @@ + diff --git a/templates/headers.hbs b/templates/headers.hbs index 3e19aa182..f94e6eea0 100644 --- a/templates/headers.hbs +++ b/templates/headers.hbs @@ -1,9 +1,9 @@ - - - - - - + + + + + + @@ -19,6 +19,11 @@ + + + @@ -29,5 +34,5 @@ - - + + diff --git a/templates/nav.hbs b/templates/nav.hbs index d63976122..67fb224a5 100644 --- a/templates/nav.hbs +++ b/templates/nav.hbs @@ -13,5 +13,11 @@
  • Tools
  • Governance
  • Community
  • + From 614b18bf92e8fe7f281df20d4da00c553d5fa10c Mon Sep 17 00:00:00 2001 From: apiraino Date: Mon, 26 Aug 2024 17:34:38 +0200 Subject: [PATCH 4/4] Style Rust logo --- src/styles/app.scss | 12 +++++++++--- src/styles/noscript.scss | 2 ++ templates/headers.hbs | 16 ++++++++-------- templates/nav.hbs | 2 +- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/styles/app.scss b/src/styles/app.scss index 227e7821b..2d53046af 100644 --- a/src/styles/app.scss +++ b/src/styles/app.scss @@ -30,6 +30,7 @@ $header-font: 'Alfa Slab One', serif; --theme-popup-bg: white; --theme-hover: #cacaca; --theme-choice-color: black; + --rust-logo-filter: initial; } // Dark theme @@ -57,6 +58,7 @@ $header-font: 'Alfa Slab One', serif; --theme-popup-bg: #141617; --theme-hover: #474c51; --theme-choice-color: #d5cbc6; + --rust-logo-filter: drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff); } html { @@ -79,7 +81,7 @@ body { display: flex; flex-direction: column; & > #main-content { - flex: 1; + flex: 1; } } @@ -192,7 +194,7 @@ div.brand { } .white { - color: var(--white-elem-color); + color: var(--white-elem-color); .highlight { background-color: var(--yellow); } @@ -334,7 +336,7 @@ h3, .post h2, header h2 { h2 { font-size: 2em; } - + h3 { display: block; } @@ -418,3 +420,7 @@ header h1 { li.theme-item:hover { background-color: var(--theme-hover); } + +.rust-logo { + filter: var(--rust-logo-filter); +} diff --git a/src/styles/noscript.scss b/src/styles/noscript.scss index ced45fe5e..94a877e0c 100644 --- a/src/styles/noscript.scss +++ b/src/styles/noscript.scss @@ -21,6 +21,7 @@ --nav-links-a: #2a3439; --publish-date-author: #2a3439; --section-header-h2-color: black; + --rust-logo-filter: initial; } // Dark theme (probed from user prefs) @@ -44,6 +45,7 @@ --nav-links-a: #d5cbc6; --publish-date-author: #d5cbc6; --section-header-h2-color: white; + --rust-logo-filter: drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff); } } diff --git a/templates/headers.hbs b/templates/headers.hbs index f94e6eea0..fb4b824ae 100644 --- a/templates/headers.hbs +++ b/templates/headers.hbs @@ -1,9 +1,9 @@ - - - - - - + + + + + + @@ -34,5 +34,5 @@ - - + + diff --git a/templates/nav.hbs b/templates/nav.hbs index 67fb224a5..36d1da5ed 100644 --- a/templates/nav.hbs +++ b/templates/nav.hbs @@ -1,7 +1,7 @@