Skip to content

Commit 662cc94

Browse files
committed
Add theme selector
1 parent ee2f8cf commit 662cc94

File tree

7 files changed

+169
-27
lines changed

7 files changed

+169
-27
lines changed

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ impl<'a> Generator<'a> {
8888
self.render_blog(blog)?;
8989
}
9090
self.compile_sass("app")?;
91+
self.compile_sass("noscript")?;
9192
self.compile_sass("fonts")?;
9293
self.concat_vendor_css(vec!["skeleton", "tachyons"])?;
9394
self.copy_static_files()?;

src/styles/app.scss

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
$body-font: 'Fira Sans', Helvetica, Arial, sans-serif;
44
$header-font: 'Alfa Slab One', serif;
55

6+
// Switching theme will only work if JavaScript is enabled as well
7+
68
// Default light theme
7-
:root {
9+
:root, :root:not([data-theme]) {
810
--gray: #2a3439;
911
--red: #a72145;
1012
--yellow: #ffc832;
@@ -23,27 +25,38 @@ $header-font: 'Alfa Slab One', serif;
2325
--nav-links-a: #2a3439;
2426
--publish-date-author: #2a3439;
2527
--section-header-h2-color: black;
28+
--theme-icon: #43484d;
29+
--theme-popup-border: #43484d;
30+
--theme-popup-bg: white;
31+
--theme-hover: #cacaca;
32+
--theme-choice-color: black;
2633
}
2734

2835
// Dark theme
29-
@media (prefers-color-scheme: dark) {
30-
:root {
31-
--code-color: white;
32-
--code-bg-color: rgba(213, 203, 198, 0.05);
33-
--code-border-color: rgba(213, 203, 198, 0.25);
34-
--blockquote-color: rgb(195, 205, 210);
35-
--blockquote-bg-color: rgba(213, 203, 198, 0.05);
36-
--blockquote-left-border-color: rgb(195, 205, 210);
37-
--body-background-color: #181a1b;
38-
--body-foreground-color: #e8e6e3;
39-
--body-color: white;
40-
--div-brand-a-color: white;
41-
--white-elem-color: white;
42-
--white-elem-a: #d5cbc6;
43-
--nav-links-a: #d5cbc6;
44-
--publish-date-author: #d5cbc6;
45-
--section-header-h2-color: white;
46-
}
36+
:root[data-theme='dark'] {
37+
--gray: #2a3439;
38+
--red: #a72145;
39+
--yellow: #ffc832;
40+
--code-color: white;
41+
--code-bg-color: rgba(213, 203, 198, 0.05);
42+
--code-border-color: rgba(213, 203, 198, 0.25);
43+
--blockquote-color: rgb(195, 205, 210);
44+
--blockquote-bg-color: rgba(213, 203, 198, 0.05);
45+
--blockquote-left-border-color: rgb(195, 205, 210);
46+
--body-background-color: #181a1b;
47+
--body-foreground-color: #e8e6e3;
48+
--body-color: white;
49+
--div-brand-a-color: white;
50+
--white-elem-color: white;
51+
--white-elem-a: #d5cbc6;
52+
--nav-links-a: #d5cbc6;
53+
--publish-date-author: #d5cbc6;
54+
--section-header-h2-color: white;
55+
--theme-icon: #43484d;
56+
--theme-popup-border: #43484d;
57+
--theme-popup-bg: #141617;
58+
--theme-hover: #474c51;
59+
--theme-choice-color: #d5cbc6;
4760
}
4861

4962
html {
@@ -363,3 +376,38 @@ header h1 {
363376
border-top-left-radius: 0;
364377
}
365378
}
379+
380+
// Theme switch popup
381+
// theme selector visible only if JavaScript is available
382+
383+
.theme-container {
384+
position: relative;
385+
}
386+
387+
.theme-icon {
388+
display: none;
389+
text-align: center;
390+
width: 2em;
391+
height: 2em;
392+
line-height: 2em;
393+
border: 1px solid var(--theme-icon);
394+
border-radius: 5px;
395+
user-select: none;
396+
cursor: pointer;
397+
}
398+
399+
.theme-choice {
400+
display: none;
401+
border: 2px solid var(--theme-popup-border);
402+
border-radius: 5px;
403+
color: var(--theme-choice-color);
404+
background: var(--theme-popup-bg);
405+
position: absolute;
406+
list-style: none;
407+
margin: 10px 10px 0px 0px;
408+
padding: 5px 5px;
409+
}
410+
411+
li.theme-item:hover {
412+
background-color: var(--theme-hover);
413+
}

src/styles/noscript.scss

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// This stylesheet is used when the user agent has no JavaScript capabilities (or has it disabled)
2+
// Sets dark theme according to user agent preferences
3+
4+
// Default light theme
5+
:root, :root:not([data-theme]) {
6+
--gray: #2a3439;
7+
--red: #a72145;
8+
--yellow: #ffc832;
9+
--code-color: black;
10+
--code-bg-color: rgba(42, 52, 57, 0.05);
11+
--code-border-color: rgba(42, 52, 57, 0.25);
12+
--blockquote-color: black;
13+
--blockquote-bg-color: rgb(247, 249, 249);
14+
--blockquote-left-border-color: rgb(195, 205, 210);
15+
--body-background-color: white;
16+
--body-foreground-color: white;
17+
--body-color: rgb(34,34,34);
18+
--div-brand-a-color: black;
19+
--white-elem-color: black;
20+
--white-a: #2a3439;
21+
--nav-links-a: #2a3439;
22+
--publish-date-author: #2a3439;
23+
--section-header-h2-color: black;
24+
}
25+
26+
// Dark theme (probed from user prefs)
27+
@media (prefers-color-scheme: dark) {
28+
:root, :root:not([data-theme]) {
29+
--gray: #2a3439;
30+
--red: #a72145;
31+
--yellow: #ffc832;
32+
--code-color: white;
33+
--code-bg-color: rgba(213, 203, 198, 0.05);
34+
--code-border-color: rgba(213, 203, 198, 0.25);
35+
--blockquote-color: rgb(195, 205, 210);
36+
--blockquote-bg-color: rgba(213, 203, 198, 0.05);
37+
--blockquote-left-border-color: rgb(195, 205, 210);
38+
--body-background-color: #181a1b;
39+
--body-foreground-color: #e8e6e3;
40+
--body-color: white;
41+
--div-brand-a-color: white;
42+
--white-elem-color: white;
43+
--white-elem-a: #d5cbc6;
44+
--nav-links-a: #d5cbc6;
45+
--publish-date-author: #d5cbc6;
46+
--section-header-h2-color: white;
47+
}
48+
}

static/scripts/theme-switch.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
function changeThemeTo(val) {
2+
document.documentElement.setAttribute("data-theme", val);
3+
// save prefs in the browser
4+
localStorage.setItem("blog-rust-lang-org-theme", val);
5+
// close the theme dropdown
6+
const themeChoice = document.getElementById("theme-choice");
7+
themeChoice.style.display = 'none';
8+
}
9+
10+
function dropdown () {
11+
const themeChoice = document.getElementById("theme-choice");
12+
// says it's more "robust" than using getPropertyValue
13+
const val = window.getComputedStyle(themeChoice).display
14+
if (val === 'none' || val === '') {
15+
themeChoice.style.display = 'block';
16+
} else {
17+
themeChoice.style.display = 'none';
18+
}
19+
}
20+
21+
// Check for saved user preference on load, else check user agent prefs
22+
const savedTheme = localStorage.getItem("blog-rust-lang-org-theme");
23+
if (savedTheme) {
24+
document.documentElement.setAttribute("data-theme", savedTheme);
25+
} else if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
26+
document.documentElement.setAttribute("data-theme", "dark");
27+
}
28+
29+
// If JavaScript is available enable theme selector
30+
const themeIcon = document.getElementById("theme-icon");
31+
themeIcon.style.display = 'block';

templates/footer.hbs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,4 @@
4444

4545
<!-- scripts -->
4646
<script src="{{root}}scripts/highlight.js"></script>
47+
<script src="{{root}}scripts/theme-switch.js"></script>

templates/headers.hbs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
<!-- Twitter card -->
2-
<meta name="twitter:card" content="summary">
3-
<meta name="twitter:site" content="@rustlang">
4-
<meta name="twitter:creator" content="@rustlang">
5-
<meta name="twitter:title" content="{{title}}">
6-
<meta name="twitter:description" content="{{blog.description}}">
1+
<!-- Twitter card -->
2+
<meta name="twitter:card" content="summary">
3+
<meta name="twitter:site" content="@rustlang">
4+
<meta name="twitter:creator" content="@rustlang">
5+
<meta name="twitter:title" content="{{title}}">
6+
<meta name="twitter:description" content="{{blog.description}}">
77
<meta name="twitter:image" content="https://www.rust-lang.org/static/images/rust-social.jpg">
88

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

22+
<!-- stylesheet for user agents without js -->
23+
<noscript>
24+
<link rel="stylesheet" href="{{root}}styles/noscript.css">
25+
</noscript>
26+
2227
<!-- favicon -->
2328
<link rel="apple-touch-icon" sizes="180x180" href="{{root}}images/apple-touch-icon.png">
2429
<link rel="icon" type="image/png" sizes="16x16" href="{{root}}images/favicon-16x16.png">
@@ -29,5 +34,6 @@
2934
<meta name="msapplication-TileColor" content="#00aba9">
3035
<meta name="theme-color" content="#ffffff">
3136

32-
<!-- atom -->
33-
<link type="application/atom+xml" rel="alternate" href="https://blog.rust-lang.org/{{blog.prefix}}feed.xml" title="{{blog.title}}" />
37+
<!-- atom -->
38+
<link type="application/atom+xml" rel="alternate" href="https://blog.rust-lang.org/{{blog.prefix}}feed.xml" title="{{blog.title}}" />
39+

templates/nav.hbs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,12 @@
1313
<li class="tc pv2 ph2 ph4-ns flex-20-s"><a href="https://www.rust-lang.org/tools">Tools</a></li>
1414
<li class="tc pv2 ph2 ph4-ns flex-20-s"><a href="https://www.rust-lang.org/governance">Governance</a></li>
1515
<li class="tc pv2 ph2 ph4-ns flex-20-s"><a href="https://www.rust-lang.org/community">Community</a></li>
16+
<div class="theme-container">
17+
<div id="theme-icon" class="theme-icon" onclick="dropdown();">🖌</div>
18+
<ul id="theme-choice" class="theme-choice">
19+
<li class="theme-item" onclick="changeThemeTo('light')">Light</li>
20+
<li class="theme-item" onclick="changeThemeTo('dark')">Dark</li>
21+
</ul>
22+
</div>
1623
</ul>
1724
</nav>

0 commit comments

Comments
 (0)