Skip to content

Commit b69cc87

Browse files
JManion32bmcutler
andauthored
[UI/UX:System] Dark Mode Toggle (#691)
## What's new? 1) Added a dark mode toggle to the sidebar. 2) Added `_colors.scss` so that colors can change dynamically. 3) Added '_dark-mode.scss` which overrides existing background and text color styling, and styles the toggle button. <img width="810" height="193" alt="image" src="https://github.com/user-attachments/assets/cc67ab50-3723-45ee-be10-3cb92f4fd00c" /> https://github.com/user-attachments/assets/ad18d5d8-ef68-44dd-8351-adaff4d3f107 --------- Co-authored-by: Barb Cutler <[email protected]>
1 parent 60a0f42 commit b69cc87

File tree

12 files changed

+269
-42
lines changed

12 files changed

+269
-42
lines changed

Gemfile.lock

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ GEM
4040
faraday-net_http (3.1.1)
4141
net-http
4242
ffi (1.17.0-arm64-darwin)
43+
ffi (1.17.0-x64-mingw-ucrt)
4344
ffi (1.17.0-x86_64-linux-gnu)
4445
forwardable-extended (2.6.0)
4546
gemoji (4.1.0)
@@ -240,6 +241,8 @@ GEM
240241
uri
241242
nokogiri (1.16.7-arm64-darwin)
242243
racc (~> 1.4)
244+
nokogiri (1.16.7-x64-mingw-ucrt)
245+
racc (~> 1.4)
243246
nokogiri (1.16.7-x86_64-linux)
244247
racc (~> 1.4)
245248
octokit (4.25.1)
@@ -277,18 +280,21 @@ GEM
277280
concurrent-ruby (~> 1.0)
278281
unicode-display_width (1.8.0)
279282
uri (0.13.0)
283+
wdm (0.2.0)
280284
webrick (1.9.1)
281285
yell (2.2.2)
282286

283287
PLATFORMS
284288
arm64-darwin-22
285289
arm64-darwin-23
290+
x64-mingw-ucrt
286291
x86_64-linux
287292

288293
DEPENDENCIES
289294
github-pages (= 232)
290295
html-proofer (~> 3.19.4)
291296
json
297+
wdm (>= 0.1.1)
292298
webrick (~> 1.9)
293299

294300
BUNDLED WITH

_layouts/default.html

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@
66
<meta name="viewport" content="width=device-width, initial-scale=1">
77
<meta name="generator" content="Jekyll v{{ jekyll.version }}">
88

9+
<script>
10+
const m = localStorage.getItem('site_mode') || 'light';
11+
document.documentElement.setAttribute('data-theme', m);
12+
const logo = document.getElementById('site-logo');
13+
if (logo) {
14+
logo.src = m === 'dark'
15+
? logo.dataset.dark
16+
: logo.dataset.light;
17+
}
18+
</script>
19+
920
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Merriweather:400,400italic,700,700italic|Open+Sans:400,400italic,600,600italic,700,700italic|Inconsolata:400,700">
1021
<link rel="stylesheet" href="{{ site.baseurl }}/css/main.css">
1122
<link rel="apple-touch-icon" href="{{ site.baseurl }}/apple-touch-icon.png">
@@ -48,23 +59,44 @@ <h1>
4859
<button type="button" class="open-nav" id="open-nav">
4960
<i class="fas fa-bars" style="color: #bbbbbb; font-size: 5.5em;"></i>
5061
</button>
51-
<a href="{{ site.baseurl }}/"><img src="{{ site.baseurl }}/images/submitty_logo.png" alt="{{ site.title }} logo"></a>
62+
<a href="{{ site.baseurl }}/" class="logo-link">
63+
<img
64+
id="site-logo"
65+
src="{{ site.baseurl }}/images/submitty_logo.png"
66+
data-light="{{ site.baseurl }}/images/submitty_logo.png"
67+
data-dark="{{ site.baseurl }}/images/submitty_logo_white.png"
68+
alt="{{ site.title }} logo"
69+
>
70+
</a>
5271
<!--{{ site.title }}-->
5372
</h1>
5473
<form action="{{ site.baseurl }}/search/" method="get">
5574
<input type="text" name="q" id="search-input" placeholder="Search" aria-label="Search content on submitty.org">
5675
<input type="submit" value="Search" style="display: none;">
5776
</form>
5877
<div id="nav-tree" class="menus medbg noxscroll mobile-invisible mobile-toggle">
59-
<div id="nav-tree-contents" class="medbg noxscroll mobile-invisible mobile-toggle">
60-
</div>
78+
<div id="nav-tree-contents" class="medbg noxscroll mobile-invisible mobile-toggle"></div>
6179
<div>&nbsp;</div>
6280
</div>
6381
<script type="text/javascript">
6482
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
6583
$(document).ready(function(){initNavTree('{{page.url}}',''); });
6684
/* @license-end */
6785
</script>
86+
<div class="dark-mode-container mobile-invisible mobile-toggle">
87+
<label class="dark-mode-switch">
88+
<input type="checkbox" id="dark-mode-toggle" />
89+
<span class="slider">
90+
<img
91+
id="dark-mode-icon"
92+
src="/images/sun_black.png"
93+
data-light="/images/sun_black.png"
94+
data-dark="/images/moon_white.png"
95+
alt="mode icon"
96+
/>
97+
</span>
98+
</label>
99+
</div>
68100
</header>
69101
<section class="main">
70102
<div class="page-header">

_sass/_colors.scss

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// _sass/_colors.scss
2+
3+
// Light theme tokens
4+
:root {
5+
--body-bg: #ffffff;
6+
--content-bg: #ffffff;
7+
--link-color: #4A4A4A;
8+
--standard-black: #000000;
9+
--content-color: #222222;
10+
--nav-bg: #f6fbfe;
11+
--nav-text: #666666;
12+
--nav-selected: #d9edf7;
13+
--brand-color: #f6fbfe;
14+
--page-header: #888888;
15+
--inline-code-color: #393318;
16+
--inline-code-bg: #F0F0F0;
17+
--even-table: #FCFCFC;
18+
19+
--toggle-thumb: #ffffff;
20+
--toggle-track: #ccc;
21+
}
22+
23+
// Dark theme overrides
24+
:root[data-theme="dark"] {
25+
--body-bg: #36393f;
26+
--content-bg: #36393f;
27+
--link-color: #bbbbbb;
28+
--standard-black: #ffffff;
29+
--content-color: #ffffff;
30+
--nav-bg: #202225;
31+
--nav-text: #cccccc;
32+
--nav-selected: #535353;
33+
--brand-color: #000000;
34+
--page-header: #999999;
35+
--inline-code-color: #FFFFFF;
36+
--inline-code-bg: #535353;
37+
--even-table: #2f3137;
38+
39+
--toggle-thumb: #000000;
40+
--toggle-track: #4d4d4d;
41+
}

_sass/_dark-mode.scss

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
// This page overrides all of the existing colors on the site with
2+
// dynamic CSS variables.
3+
4+
@import "colors";
5+
6+
body {
7+
background-color: var(--body-bg);
8+
}
9+
10+
header.main-nav {
11+
background-color: var(--nav-bg);
12+
display: flex;
13+
flex-direction: column;
14+
}
15+
16+
a {
17+
color: var(--link-color);
18+
}
19+
20+
a:hover {
21+
color: var(--standard-black) !important;
22+
}
23+
24+
.page-header h2 {
25+
color: var(--page-header);
26+
}
27+
28+
h2 {
29+
color: var(--content-color);
30+
}
31+
32+
h3 {
33+
color: var(--content-color);
34+
}
35+
36+
h4 {
37+
color: var(--content-color);
38+
}
39+
40+
#nav-tree .selected {
41+
background-color: var(--nav-selected) !important;
42+
}
43+
44+
#nav-tree .selected a {
45+
color: var(--content-color) !important;
46+
text-shadow: none !important;
47+
font-weight: bold;
48+
}
49+
50+
.arrow {
51+
color: var(--content-color) !important;
52+
}
53+
54+
#search-input {
55+
background-color: var(--content-bg);
56+
color: var(--content-color);
57+
}
58+
59+
// Inline code snippets, such as on the Contact Us page
60+
pre, code, tt {
61+
background-color: var(--inline-code-bg);
62+
color: var(--inline-code-color);
63+
}
64+
65+
button {
66+
background-color: transparent !important;
67+
}
68+
69+
tr {
70+
border-bottom: 1px solid #EEE;
71+
72+
&:nth-child(even) {
73+
background: var(--even-table);
74+
}
75+
}
76+
77+
span[id^="mytag"] {
78+
background-color: var(--inline-code-bg) !important;
79+
color: var(--inline-code-color) !important;
80+
padding: 10px;
81+
}
82+
83+
*,
84+
*::before,
85+
*::after {
86+
transition:
87+
color 200ms ease-in-out,
88+
background-color 200ms ease-in-out;
89+
}
90+
91+
.dark-mode-container {
92+
margin-top: auto;
93+
margin-bottom: 20px;
94+
align-self: center;
95+
}
96+
97+
.dark-mode-switch {
98+
position: relative;
99+
display: inline-block;
100+
width: 50px;
101+
height: 28px;
102+
margin-bottom: 20px;
103+
align-self: center;
104+
}
105+
106+
.dark-mode-switch input {
107+
opacity: 0;
108+
width: 0;
109+
height: 0;
110+
}
111+
112+
.dark-mode-switch .slider {
113+
position: absolute;
114+
inset: 0;
115+
cursor: pointer;
116+
background-color: var(--toggle-track);
117+
border-radius: 34px;
118+
transition: background-color 0.3s ease;
119+
}
120+
121+
.dark-mode-switch .slider img {
122+
position: absolute;
123+
left: 3px;
124+
top: 3px;
125+
width: 22px;
126+
height: 22px;
127+
border-radius: 50%;
128+
background-color: var(--toggle-thumb);
129+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
130+
transition: transform 0.3s ease, background-color 0.3s ease;
131+
user-select: none;
132+
-webkit-user-drag: none;
133+
display: none;
134+
}
135+
136+
.dark-mode-switch .slider img[src] {
137+
display: block;
138+
}
139+
140+
.dark-mode-switch input:checked + .slider img {
141+
transform: translateX(22px);
142+
}

0 commit comments

Comments
 (0)