Skip to content

Commit

Permalink
Add theme selector
Browse files Browse the repository at this point in the history
  • Loading branch information
apiraino committed Aug 14, 2024
1 parent ee2f8cf commit 0030b2b
Show file tree
Hide file tree
Showing 8 changed files with 188 additions and 27 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ site
static/styles/vendor.css
static/styles/app.css
static/styles/fonts.css
static/styles/noscript.css
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()?;
Expand Down
87 changes: 68 additions & 19 deletions src/styles/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 {
Expand Down Expand Up @@ -363,3 +376,39 @@ header h1 {
border-top-left-radius: 0;
}
}

// Theme switch popup
// theme selector visible only if JavaScript is available

.theme-icon {
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 5px;
// counterbalance vendored skeleton.css
margin: 0.2em -0.5em;
}

#theme-choice.showThemeDropdown {
display: block;
}

li.theme-item:hover {
background-color: var(--theme-hover);
}
53 changes: 53 additions & 0 deletions src/styles/noscript.scss
Original file line number Diff line number Diff line change
@@ -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;
}
45 changes: 45 additions & 0 deletions static/scripts/theme-switch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
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
);
}
}


// 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");
}
1 change: 1 addition & 0 deletions templates/footer.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,4 @@

<!-- scripts -->
<script src="{{root}}scripts/highlight.js"></script>
<script src="{{root}}scripts/theme-switch.js"></script>
21 changes: 13 additions & 8 deletions templates/headers.hbs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<!-- Twitter card -->
<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="@rustlang">
<meta name="twitter:creator" content="@rustlang">
<meta name="twitter:title" content="{{title}}">
<meta name="twitter:description" content="{{blog.description}}">
<!-- Twitter card -->
<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="@rustlang">
<meta name="twitter:creator" content="@rustlang">
<meta name="twitter:title" content="{{title}}">
<meta name="twitter:description" content="{{blog.description}}">
<meta name="twitter:image" content="https://www.rust-lang.org/static/images/rust-social.jpg">

<!-- Facebook OpenGraph -->
Expand All @@ -19,6 +19,11 @@
<link rel="stylesheet" href="{{root}}styles/app.css"/>
<link rel="stylesheet" href="{{root}}styles/highlight.css"/>

<!-- stylesheet for user agents without js -->
<noscript>
<link rel="stylesheet" href="{{root}}styles/noscript.css">
</noscript>

<!-- favicon -->
<link rel="apple-touch-icon" sizes="180x180" href="{{root}}images/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="16x16" href="{{root}}images/favicon-16x16.png">
Expand All @@ -29,5 +34,5 @@
<meta name="msapplication-TileColor" content="#00aba9">
<meta name="theme-color" content="#ffffff">

<!-- atom -->
<link type="application/atom+xml" rel="alternate" href="https://blog.rust-lang.org/{{blog.prefix}}feed.xml" title="{{blog.title}}" />
<!-- atom -->
<link type="application/atom+xml" rel="alternate" href="https://blog.rust-lang.org/{{blog.prefix}}feed.xml" title="{{blog.title}}" />
6 changes: 6 additions & 0 deletions templates/nav.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,11 @@
<li class="tc pv2 ph2 ph4-ns flex-20-s"><a href="https://www.rust-lang.org/tools">Tools</a></li>
<li class="tc pv2 ph2 ph4-ns flex-20-s"><a href="https://www.rust-lang.org/governance">Governance</a></li>
<li class="tc pv2 ph2 ph4-ns flex-20-s"><a href="https://www.rust-lang.org/community">Community</a></li>
<button class="theme-icon" onclick="dropdown();">🖌
<ul id="theme-choice">
<li class="theme-item" onclick="changeThemeTo('light');">Light</li>
<li class="theme-item" onclick="changeThemeTo('dark');">Dark</li>
</ul>
</button>
</ul>
</nav>

0 comments on commit 0030b2b

Please sign in to comment.