Skip to content

Commit e11047f

Browse files
committed
Add support for dark and light theme.
1 parent bc13c80 commit e11047f

File tree

3 files changed

+128
-2
lines changed

3 files changed

+128
-2
lines changed

examples/device/webusb_serial/website/application.js

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
(async () => {
44
// bind to the html
5+
const uiBody = document.body;
6+
const uiToggleThemeBtn = document.getElementById('theme-toggle');
7+
58
const uiConnectWebUsbSerialBtn = document.getElementById('connect_webusb_serial_btn');
69
const uiConnectSerialBtn = document.getElementById('connect_serial_btn');
710
const uiDisconnectBtn = document.getElementById('disconnect_btn');
@@ -27,7 +30,9 @@
2730
const uiNearTheBottomThreshold = 100; // pixels from the bottom to trigger scroll
2831

2932
const maxCommandHistoryLength = 123; // max number of command history entries
30-
const maxReceivedDataLength = 8192/8; // max number of received data entries
33+
const maxReceivedDataLength = 8192 / 8; // max number of received data entries
34+
35+
const THEME_STATES = ['auto', 'light', 'dark'];
3136

3237
class CommandHistoryEntry {
3338
constructor(text) {
@@ -59,6 +64,16 @@
5964
this.receivedData = [];
6065

6166
// bind the UI elements
67+
uiToggleThemeBtn.addEventListener('click', () => this.toggleTheme());
68+
// Listener for OS Theme Changes
69+
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
70+
const currentPreference = localStorage.getItem('theme') || 'auto';
71+
// Only act if the user is in automatic mode
72+
if (currentPreference === 'auto') {
73+
this.setTheme('auto');
74+
}
75+
});
76+
6277
uiConnectWebUsbSerialBtn.addEventListener('click', () => this.connectWebUsbSerialPort());
6378
uiConnectSerialBtn.addEventListener('click', () => this.connectSerialPort());
6479
uiDisconnectBtn.addEventListener('click', () => this.disconnectPort());
@@ -88,6 +103,12 @@
88103
}
89104

90105
restoreState() {
106+
// Restore theme choice
107+
const savedTheme = localStorage.getItem('theme');
108+
if (savedTheme) {
109+
this.setTheme(savedTheme);
110+
}
111+
91112
// Restore command history
92113
let savedCommandHistory = JSON.parse(localStorage.getItem('commandHistory') || '[]');
93114
for (const cmd of savedCommandHistory) {
@@ -112,6 +133,38 @@
112133
}
113134
}
114135

136+
setTheme(theme) {
137+
const modeName = theme.charAt(0).toUpperCase() + theme.slice(1);
138+
uiToggleThemeBtn.textContent = `Theme: ${modeName}`;
139+
140+
if (theme === 'auto') {
141+
// In auto mode, we rely on the OS preference.
142+
// We check the media query and add/remove the class accordingly.
143+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
144+
if (prefersDark) {
145+
uiBody.classList.add('dark-mode');
146+
} else {
147+
uiBody.classList.remove('dark-mode');
148+
}
149+
} else if (theme === 'light') {
150+
// Force light mode by removing the class.
151+
uiBody.classList.remove('dark-mode');
152+
} else if (theme === 'dark') {
153+
// Force dark mode by adding the class.
154+
uiBody.classList.add('dark-mode');
155+
}
156+
157+
// Save the theme to localStorage
158+
localStorage.setItem('theme', theme);
159+
}
160+
161+
toggleTheme() {
162+
const currentTheme = localStorage.getItem('theme') || 'auto';
163+
const nextThemeIndex = (THEME_STATES.indexOf(currentTheme) + 1) % THEME_STATES.length;
164+
const nextTheme = THEME_STATES[nextThemeIndex];
165+
this.setTheme(nextTheme);
166+
}
167+
115168
appendCommandToHistory(commandHistoryEntry) {
116169
const wasNearBottom = uiCommandHistoryScrollbox.scrollHeight - uiCommandHistoryScrollbox.scrollTop <= uiCommandHistoryScrollbox.clientHeight + uiNearTheBottomThreshold;
117170

examples/device/webusb_serial/website/index.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313

1414
<body>
1515
<header class="header">
16-
<h1 class="title">TinyUSB - WebUSB Serial</h1>
16+
<h1 class="app-title">TinyUSB - WebUSB Serial</h1>
17+
<button id="theme-toggle" class="btn btn-theme">Theme: Auto</button>
1718
<a class="github-link" href="https://github.com/hathach/tinyusb/tree/master/examples/device/webusb_serial/website"
1819
target="_blank">
1920
Find my source on GitHub

examples/device/webusb_serial/website/style.css

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ body {
2525
justify-content: space-between;
2626
align-items: center;
2727
padding: 0.5em 1em;
28+
gap: 1em;
2829
flex-shrink: 0;
2930
}
3031

@@ -33,6 +34,15 @@ h2 {
3334
margin: 0;
3435
}
3536

37+
.app-title {
38+
flex-grow: 1;
39+
}
40+
41+
.btn-theme {
42+
background-color: #6b6b6b;
43+
color: #fff;
44+
}
45+
3646
.github-link {
3747
font-weight: 600;
3848
}
@@ -198,3 +208,65 @@ main {
198208
cursor: col-resize;
199209
height: 100%;
200210
}
211+
212+
/*
213+
================================
214+
Togglable Dark Mode
215+
================================
216+
*/
217+
/* This class will be added to the body element by JavaScript */
218+
body.dark-mode {
219+
/* Invert base background and text colors */
220+
background: #1e1e1e;
221+
color: #d4d4d4;
222+
}
223+
224+
body.dark-mode .btn-theme {
225+
background-color: #b0b0b0;
226+
color: #000;
227+
}
228+
229+
body.dark-mode .github-link {
230+
color: #58a6ff;
231+
}
232+
233+
body.dark-mode .resizer {
234+
background-color: #444;
235+
}
236+
237+
body.dark-mode .input {
238+
background-color: #3c3c3c;
239+
color: #f0f0f0;
240+
border: 2px solid #555;
241+
}
242+
243+
body.dark-mode .input::placeholder {
244+
color: #888;
245+
}
246+
247+
body.dark-mode .input:focus {
248+
background-color: #2a2d2e;
249+
border-color: #0078d7;
250+
}
251+
252+
body.dark-mode .scrollbox {
253+
background-color: #252526;
254+
border: 1px solid #444;
255+
}
256+
257+
body.dark-mode .monospaced {
258+
color: #d4d4d4;
259+
}
260+
261+
body.dark-mode .command-history-entry {
262+
border-bottom: 1px solid #444;
263+
}
264+
265+
body.dark-mode .command-history-entry:hover {
266+
background-color: #3c3c3c;
267+
}
268+
269+
body.dark-mode .send-mode-command {
270+
background-color: #555;
271+
color: #f5f5f5;
272+
}

0 commit comments

Comments
 (0)