Move colors to variables and fix up UI

This commit is contained in:
Owen G
2026-01-04 16:00:42 -07:00
parent b15787abca
commit 7f88a45ae7
6 changed files with 157 additions and 25 deletions
+1
View File
@@ -2,3 +2,4 @@ node_modules
data
.DS_Store
.env
.vscode
+40 -2
View File
@@ -4,6 +4,10 @@ const canvas = document.getElementById('network');
const ctx = canvas.getContext('2d');
let particles = [];
function getThemeColor(varName) {
return getComputedStyle(document.documentElement).getPropertyValue(varName).trim();
}
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
@@ -32,7 +36,7 @@ class Particle {
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fillStyle = '#4ade80';
ctx.fillStyle = getThemeColor('--color-particle');
ctx.fill();
}
}
@@ -54,7 +58,7 @@ const updateParticles = (count) => {
const animate = () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.strokeStyle = 'rgba(74, 222, 128, 0.15)';
ctx.strokeStyle = getThemeColor('--color-particle-link');
ctx.lineWidth = 1;
for (let i = 0; i < particles.length; i++) {
for (let j = i + 1; j < particles.length; j++) {
@@ -154,3 +158,37 @@ countEl.classList.add('loaded');
updateParticles(initialCount);
animate();
const themes = [
'default.css',
'tokyo-night.css'
];
let currentThemeIndex = 0;
function loadSavedTheme() {
const savedTheme = localStorage.getItem('hypermind-theme');
if (savedTheme) {
const themeLink = document.getElementById('theme-css');
themeLink.href = `/themes/${savedTheme}`;
currentThemeIndex = themes.indexOf(savedTheme);
if (currentThemeIndex === -1) currentThemeIndex = 0;
} else {
const themeLink = document.getElementById('theme-css');
const currentTheme = themeLink.href.split('/').pop();
currentThemeIndex = themes.indexOf(currentTheme);
if (currentThemeIndex === -1) currentThemeIndex = 0;
}
}
function cycleTheme() {
currentThemeIndex = (currentThemeIndex + 1) % themes.length;
const newTheme = themes[currentThemeIndex];
const themeLink = document.getElementById('theme-css');
themeLink.href = `/themes/${newTheme}`;
localStorage.setItem('hypermind-theme', newTheme);
}
document.getElementById('theme-switcher').addEventListener('click', cycleTheme);
loadSavedTheme();
+5 -1
View File
@@ -4,6 +4,7 @@
<title>Hypermind</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="/favicon.ico">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0&icon_names=palette" /> <link rel="stylesheet" href="/themes/tokyo-night.css" id="theme-css">
<link rel="stylesheet" href="/style.css">
</head>
<body>
@@ -12,7 +13,7 @@
<div id="count" class="count" data-initial-count="{{COUNT}}">{{COUNT}}</div>
<div class="label">Active Nodes</div>
<div class="footer">
powered by <a href="https://github.com/lklynet/hypermind" target="_blank">hypermind</a>
powered by <a href="https://github.com/lklynet/hypermind" target="_blank" class="footer-link">hypermind</a>
</div>
<div class="debug">
ID: {{ID}}<br>
@@ -65,6 +66,9 @@
</div>
</div>
<button id="theme-switcher" class="theme-btn" title="Cycle Themes">
<span class="material-symbols-outlined">palette</span>
</button>
<script src="/app.js"></script>
</body>
+56 -22
View File
@@ -6,29 +6,37 @@ body {
justify-content: center;
align-items: center;
height: 100vh;
background: #111;
color: #eee;
background: var(--color-bg-main);
color: var(--color-text-default);
margin: 0;
}
.container { text-align: center; position: relative; z-index: 10; }
#network { position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 1; }
.count { font-size: 8rem; font-weight: bold; color: #4ade80; transition: color 0.2s; visibility: hidden; }
.count { font-size: 8rem; font-weight: bold; color: var(--color-count); transition: color 0.2s; visibility: hidden; }
.count.loaded { visibility: visible; }
.label { font-size: 1.5rem; color: #9ca3af; margin-top: 1rem; }
.footer { margin-top: 2rem; font-size: 0.9rem; color: #4b5563; }
.debug { font-size: 0.8rem; color: #4b5563; margin-top: 1rem; }
.debug-link { color: #4b5563; border-bottom: 1px dotted #4b5563; cursor: pointer; }
.debug-link:hover { color: #9ca3af; }
a { color: #4b5563; text-decoration: none; border-bottom: 1px dotted #4b5563; }
.label { font-size: 1.5rem; color: var(--color-text-main-label); margin-top: 1rem; }
.footer { margin-top: 2rem; font-size: 0.9rem; color: var(--color-text-footer); }
.debug { font-size: 0.8rem; color: var(--color-text-debug); margin-top: 1rem; }
.debug-link { color: var(--color-text-debug-link); border-bottom: 1px dotted; cursor: pointer; transition: color 0.2s; }
.debug-link:hover { color: var(--color-text-debug-link-hover); }
a { color: var(--color-text-secondary); text-decoration: none; border-bottom: 1px dotted var(--color-text-secondary); }
.pulse { animation: pulse 0.5s ease-in-out; }
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.1); color: #fff; }
50% { transform: scale(1.1); color: var(--color-pulse); }
100% { transform: scale(1); }
}
.footer a {
color: var(--color-text-footer);
border-bottom: 1px dotted var(--color-text-footer);
cursor: pointer;
transition: color 0.2s, border-color 0.2s;
}
.footer a:hover {
color: var(--color-text-footer-hover);
border-color: var(--color-text-footer-hover);
}
.modal {
display: none;
position: fixed;
@@ -37,12 +45,12 @@ a { color: #4b5563; text-decoration: none; border-bottom: 1px dotted #4b5563; }
top: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
background: var(--color-bg-overlay);
}
.modal.active { display: flex; align-items: center; justify-content: center; }
.modal-content {
background: #111;
border: 1px solid #222;
background: var(--color-modal-bg);
border: 1px solid var(--color-modal-border);
padding: 2rem;
max-width: 500px;
width: 90%;
@@ -50,7 +58,7 @@ a { color: #4b5563; text-decoration: none; border-bottom: 1px dotted #4b5563; }
}
.modal-title {
font-size: 0.9rem;
color: #666;
color: var(--color-modal-title);
margin-bottom: 1.5rem;
text-transform: uppercase;
letter-spacing: 1px;
@@ -61,27 +69,53 @@ a { color: #4b5563; text-decoration: none; border-bottom: 1px dotted #4b5563; }
right: 1.5rem;
background: none;
border: none;
color: #333;
color: var(--color-modal-close-btn);
font-size: 1.2rem;
cursor: pointer;
transition: color 0.2s;
}
.close-btn:hover { color: #666; }
.close-btn:hover { color: var(--color-modal-close-btn-hover); }
.stat-row {
display: flex;
justify-content: space-between;
padding: 0.5rem 0;
border-bottom: 1px solid #1a1a1a;
border-bottom: 1px solid var(--color-modal-stat-div);
font-size: 0.85rem;
}
.stat-row:last-child { border-bottom: none; }
.stat-label { color: #4b5563; }
.stat-label { color: var(--color-modal-stat-label); }
.stat-value {
color: #9ca3af;
color: var(--color-modal-stat-value;);
font-variant-numeric: tabular-nums;
}
.update-time {
text-align: center;
font-size: 0.7rem;
color: #333;
color: var(--color-modal-footer);
margin-top: 1rem;
}
.theme-btn {
position: fixed;
bottom: 1.5rem;
left: 1.5rem;
cursor: pointer;
z-index: 100;
display: flex;
align-items: center;
justify-content: center;
background: none;
border: none;
padding: 0;
transition: all 0.2s ease;
}
.theme-btn .material-symbols-outlined {
color: var(--color-theme-toggle);
font-size: 28px;
font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
transition: color 0.2s ease;
}
.theme-btn:hover .material-symbols-outlined {
color: var(--color-theme-toggle-hover);
}
+31
View File
@@ -0,0 +1,31 @@
:root {
--color-count: #4ade80;
--color-particle: #4ade80;
--color-particle-link: rgba(74, 222, 128, 0.15);
--color-pulse: #fff;
--color-theme-toggle: #4ade80;
--color-theme-toggle-hover: #fff;
--color-text-default: #eee;
--color-text-secondary: #4b5563;
--color-text-main-label: #9ca3af;
--color-text-footer: #4b5563;
--color-text-footer-hover: #9ca3af;
--color-text-debug: #4b5563;
--color-text-debug-link: #4b5563;
--color-text-debug-link-hover: #9ca3af;
--color-bg-overlay: rgba(0, 0, 0, 0.8);
--color-bg-main: #111;
--color-modal-bg: #111;
--color-modal-border: #222;
--color-modal-title: #666;
--color-modal-close-btn: #333;
--color-modal-close-btn-hover: #666;
--color-modal-stat-div: #1a1a1a;
--color-modal-stat-label: #4b5563;
--color-modal-stat-value: #9ca3af;
--color-modal-footer: #333;
}
+24
View File
@@ -0,0 +1,24 @@
:root {
--color-primary: #ff6b6b;
--color-particle-link: rgba(255, 107, 107, 0.15);
--color-pulse: #fff;
--color-theme-toggle: #ff6b6b;
--color-theme-toggle-hover: #fff;
--color-text-default: #eee;
--color-text-primary: #f7d794;
--color-text-secondary: #ff92a1;
--color-text-tertiary: #ff92a1;
--color-bg-main: #00172e;
--color-bg-overlay: rgba(0, 1, 2, 0.8);
--color-border-light: #222;
--color-modal-close-btn: #ff92a1;
--color-modal-close-btn-hover: #f7d794;
--color-modal-stats-border: #ff92a1;
--color-modal-footer: #2d3436;
}