summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorraldone01 <[email protected]>2025-07-05 19:42:44 +0200
committerraldone01 <[email protected]>2025-07-05 19:42:44 +0200
commite11047f00367e3b32cbc966de0ad687276aa613b (patch)
treefe37214600420e1b0048e9136073c66841f4e5af /examples
parentbc13c80c630f45603ddb6a1e0435bf637580fb68 (diff)
Add support for dark and light theme.
Diffstat (limited to 'examples')
-rw-r--r--examples/device/webusb_serial/website/application.js55
-rw-r--r--examples/device/webusb_serial/website/index.html3
-rw-r--r--examples/device/webusb_serial/website/style.css72
3 files changed, 128 insertions, 2 deletions
diff --git a/examples/device/webusb_serial/website/application.js b/examples/device/webusb_serial/website/application.js
index 5be082ca2..e9528a2ba 100644
--- a/examples/device/webusb_serial/website/application.js
+++ b/examples/device/webusb_serial/website/application.js
@@ -2,6 +2,9 @@
(async () => {
// bind to the html
+ const uiBody = document.body;
+ const uiToggleThemeBtn = document.getElementById('theme-toggle');
+
const uiConnectWebUsbSerialBtn = document.getElementById('connect_webusb_serial_btn');
const uiConnectSerialBtn = document.getElementById('connect_serial_btn');
const uiDisconnectBtn = document.getElementById('disconnect_btn');
@@ -27,7 +30,9 @@
const uiNearTheBottomThreshold = 100; // pixels from the bottom to trigger scroll
const maxCommandHistoryLength = 123; // max number of command history entries
- const maxReceivedDataLength = 8192/8; // max number of received data entries
+ const maxReceivedDataLength = 8192 / 8; // max number of received data entries
+
+ const THEME_STATES = ['auto', 'light', 'dark'];
class CommandHistoryEntry {
constructor(text) {
@@ -59,6 +64,16 @@
this.receivedData = [];
// bind the UI elements
+ uiToggleThemeBtn.addEventListener('click', () => this.toggleTheme());
+ // Listener for OS Theme Changes
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
+ const currentPreference = localStorage.getItem('theme') || 'auto';
+ // Only act if the user is in automatic mode
+ if (currentPreference === 'auto') {
+ this.setTheme('auto');
+ }
+ });
+
uiConnectWebUsbSerialBtn.addEventListener('click', () => this.connectWebUsbSerialPort());
uiConnectSerialBtn.addEventListener('click', () => this.connectSerialPort());
uiDisconnectBtn.addEventListener('click', () => this.disconnectPort());
@@ -88,6 +103,12 @@
}
restoreState() {
+ // Restore theme choice
+ const savedTheme = localStorage.getItem('theme');
+ if (savedTheme) {
+ this.setTheme(savedTheme);
+ }
+
// Restore command history
let savedCommandHistory = JSON.parse(localStorage.getItem('commandHistory') || '[]');
for (const cmd of savedCommandHistory) {
@@ -112,6 +133,38 @@
}
}
+ setTheme(theme) {
+ const modeName = theme.charAt(0).toUpperCase() + theme.slice(1);
+ uiToggleThemeBtn.textContent = `Theme: ${modeName}`;
+
+ if (theme === 'auto') {
+ // In auto mode, we rely on the OS preference.
+ // We check the media query and add/remove the class accordingly.
+ const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
+ if (prefersDark) {
+ uiBody.classList.add('dark-mode');
+ } else {
+ uiBody.classList.remove('dark-mode');
+ }
+ } else if (theme === 'light') {
+ // Force light mode by removing the class.
+ uiBody.classList.remove('dark-mode');
+ } else if (theme === 'dark') {
+ // Force dark mode by adding the class.
+ uiBody.classList.add('dark-mode');
+ }
+
+ // Save the theme to localStorage
+ localStorage.setItem('theme', theme);
+ }
+
+ toggleTheme() {
+ const currentTheme = localStorage.getItem('theme') || 'auto';
+ const nextThemeIndex = (THEME_STATES.indexOf(currentTheme) + 1) % THEME_STATES.length;
+ const nextTheme = THEME_STATES[nextThemeIndex];
+ this.setTheme(nextTheme);
+ }
+
appendCommandToHistory(commandHistoryEntry) {
const wasNearBottom = uiCommandHistoryScrollbox.scrollHeight - uiCommandHistoryScrollbox.scrollTop <= uiCommandHistoryScrollbox.clientHeight + uiNearTheBottomThreshold;
diff --git a/examples/device/webusb_serial/website/index.html b/examples/device/webusb_serial/website/index.html
index 87fcfd6aa..bf02d0294 100644
--- a/examples/device/webusb_serial/website/index.html
+++ b/examples/device/webusb_serial/website/index.html
@@ -13,7 +13,8 @@
<body>
<header class="header">
- <h1 class="title">TinyUSB - WebUSB Serial</h1>
+ <h1 class="app-title">TinyUSB - WebUSB Serial</h1>
+ <button id="theme-toggle" class="btn btn-theme">Theme: Auto</button>
<a class="github-link" href="https://github.com/hathach/tinyusb/tree/master/examples/device/webusb_serial/website"
target="_blank">
Find my source on GitHub
diff --git a/examples/device/webusb_serial/website/style.css b/examples/device/webusb_serial/website/style.css
index ee9dc73ac..9530d3d55 100644
--- a/examples/device/webusb_serial/website/style.css
+++ b/examples/device/webusb_serial/website/style.css
@@ -25,6 +25,7 @@ body {
justify-content: space-between;
align-items: center;
padding: 0.5em 1em;
+ gap: 1em;
flex-shrink: 0;
}
@@ -33,6 +34,15 @@ h2 {
margin: 0;
}
+.app-title {
+ flex-grow: 1;
+}
+
+.btn-theme {
+ background-color: #6b6b6b;
+ color: #fff;
+}
+
.github-link {
font-weight: 600;
}
@@ -198,3 +208,65 @@ main {
cursor: col-resize;
height: 100%;
}
+
+/*
+================================
+Togglable Dark Mode
+================================
+*/
+/* This class will be added to the body element by JavaScript */
+body.dark-mode {
+ /* Invert base background and text colors */
+ background: #1e1e1e;
+ color: #d4d4d4;
+}
+
+body.dark-mode .btn-theme {
+ background-color: #b0b0b0;
+ color: #000;
+}
+
+body.dark-mode .github-link {
+ color: #58a6ff;
+}
+
+body.dark-mode .resizer {
+ background-color: #444;
+}
+
+body.dark-mode .input {
+ background-color: #3c3c3c;
+ color: #f0f0f0;
+ border: 2px solid #555;
+}
+
+body.dark-mode .input::placeholder {
+ color: #888;
+}
+
+body.dark-mode .input:focus {
+ background-color: #2a2d2e;
+ border-color: #0078d7;
+}
+
+body.dark-mode .scrollbox {
+ background-color: #252526;
+ border: 1px solid #444;
+}
+
+body.dark-mode .monospaced {
+ color: #d4d4d4;
+}
+
+body.dark-mode .command-history-entry {
+ border-bottom: 1px solid #444;
+}
+
+body.dark-mode .command-history-entry:hover {
+ background-color: #3c3c3c;
+}
+
+body.dark-mode .send-mode-command {
+ background-color: #555;
+ color: #f5f5f5;
+}