feat(theme): add hypermind theme with notification support

Added a new (official) hypermind theme with color scheme to match new site and a notification display when switching themes
This commit is contained in:
lklynet
2026-01-11 17:49:13 -05:00
parent 5d5217ee81
commit b7eb5ecd54
8 changed files with 112 additions and 3 deletions
+1 -1
View File
@@ -50,7 +50,7 @@ A completely decentralized chat system built directly on top of the swarm topolo
### 3. Visualizations
* **Particle Map:** Visualizes approximate peer locations (if enabled).
* **Themes:** Built-in theme switcher (Nord, Solarized, Tokyo Night, etc).<br>
<img src="assets/images/default-theme.png" width="100" alt="Default" /> <img src="assets/images/nord-dark-theme.png" width="100" alt="Nord" /> <img src="assets/images/solarized-light-theme.png" width="100" alt="Solarized" /> <img src="assets/images/tokyo-night-theme.png" width="100" alt="Tokyo Night" /> <img src="assets/images/volcano-theme.png" width="100" alt="Volcano" />
<img src="assets/images/default-theme.png" width="100" alt="Default" /> <img src="assets/images/nord-dark-theme.png" width="100" alt="Nord" /> <img src="assets/images/solarized-light-theme.png" width="100" alt="Solarized" /> <img src="assets/images/tokyo-night-theme.png" width="100" alt="Tokyo Night" /> <img src="assets/images/volcano-theme.png" width="100" alt="Volcano" /> <img src="assets/images/hypermind-theme.png" width="100" alt="Hypermind" />
---
+5
View File
@@ -20,6 +20,10 @@
![Volcano theme screenshot](assets/images/volcano-theme.png)
### Hypermind
![Hypermind theme screenshot](assets/images/hypermind-theme.png)
# Contributing custom themes
1. Fork `main` and clone locally to your device.
@@ -35,6 +39,7 @@
'nord-dark.css',
'solarized-light.css',
'volcano.css',
'hypermind.css',
'new-theme.css' /* always add to the end of the list
];
```
Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "hypermind",
"version": "0.10.0",
"version": "0.11.0",
"description": "A decentralized P2P counter of active deployments",
"main": "server.js",
"scripts": {
+30 -1
View File
@@ -823,11 +823,39 @@ const themes = [
"nord-dark.css",
"solarized-light.css",
"volcano.css",
"hypermind.css",
];
let currentThemeIndex = 0;
let notificationTimeout;
function showThemeNotification(themeName) {
const notification = document.getElementById("theme-notification");
if (!notification) return;
const displayName = themeName
.replace(".css", "")
.split("-")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");
notification.innerText = `Theme: ${displayName}`;
notification.classList.remove("hidden");
notification.offsetHeight;
notification.classList.add("show");
if (notificationTimeout) clearTimeout(notificationTimeout);
notificationTimeout = setTimeout(() => {
notification.classList.remove("show");
setTimeout(() => {
notification.classList.add("hidden");
}, 300);
}, 2000);
}
// Initialize currentThemeIndex based on the theme loaded by index.html
const currentThemeLink = document.getElementById("theme-css");
if (currentThemeLink) {
const currentThemeName = currentThemeLink.href.split("/").pop();
@@ -856,6 +884,7 @@ function cycleTheme() {
localStorage.setItem("hypermind-theme", newTheme);
btn.disabled = false;
btn.style.opacity = "";
showThemeNotification(newTheme);
};
newLink.onerror = () => {
+1
View File
@@ -124,6 +124,7 @@
<button id="theme-switcher" class="theme-btn {{THEMES_CLASS}}" title="Cycle Themes">
<span class="material-symbols-outlined">palette</span>
</button>
<div id="theme-notification" class="theme-notification hidden"></div>
<div id="terminal" class="terminal hidden">
<div id="terminal-resizer" class="terminal-resizer"></div>
<button id="terminal-toggle" class="terminal-toggle" title="Toggle Chat">
+31
View File
@@ -182,6 +182,37 @@ a { color: var(--color-text-anchor-link); text-decoration: none; border-bottom:
color: var(--color-theme-toggle-hover);
}
.theme-notification {
position: fixed;
bottom: 1.5rem;
left: 4.5rem;
background: var(--color-terminal-bg);
border: 1px solid var(--color-terminal-border);
color: var(--color-terminal-text-default);
padding: 6px 12px;
border-radius: 6px;
font-size: 0.8rem;
z-index: 1000;
pointer-events: none;
opacity: 0;
transition: opacity 0.3s ease, transform 0.3s ease;
transform: translateX(-10px);
white-space: nowrap;
box-shadow: 0 2px 8px var(--color-terminal-shadow);
display: flex;
align-items: center;
gap: 8px;
}
.theme-notification.show {
opacity: 1;
transform: translateX(0);
}
.theme-notification.hidden {
display: none;
}
.terminal {
position: fixed;
bottom: 0;
+43
View File
@@ -0,0 +1,43 @@
:root {
--color-count: #718062;
--color-particle: #718062;
--color-particle-link: rgba(113, 128, 98, 0.15);
--color-pulse: #daba8b;
--color-theme-toggle: #718062;
--color-theme-toggle-hover: #daba8b;
--color-bg-main: #191716;
--color-bg-overlay: rgba(25, 23, 22, 0.8);
--color-text-default: #daba8b;
--color-text-main-label: #a17e3e;
--color-text-footer: #65788f;
--color-text-footer-hover: #a17e3e;
--color-text-debug: #65788f;
--color-text-debug-link: #65788f;
--color-text-debug-link-hover: #a17e3e;
--color-text-anchor-link: #65788f;
--color-modal-bg: #191716;
--color-modal-border: #0f0e0d;
--color-modal-title: #8c4f4a;
--color-modal-close-btn: #0f0e0d;
--color-modal-close-btn-hover: #8c4f4a;
--color-modal-stat-div: #0f0e0d;
--color-modal-stat-label: #65788f;
--color-modal-stat-value: #a17e3e;
--color-modal-footer: #0f0e0d;
--color-terminal-bg: rgba(25, 23, 22, 0.9);
--color-terminal-border: #0f0e0d;
--color-terminal-shadow: rgba(0, 0, 0, 0.3);
--color-terminal-input-text: #daba8b;
--color-terminal-input-divider: #0f0e0d;
--color-terminal-output-message: #c8b491;
--color-terminal-tab-arrow: #718062;
--color-terminal-tab-arrow-hover: #daba8b;
--color-terminal-tab-bg-hover: #0f0e0d;
--color-terminal-status-message: #65788f;
--color-terminal-scrollbar: #a17e3e;
--color-terminal-scrollbar-hover: #8c4f4a;
--color-terminal-text-default: #718062;
}