theme switcher

This commit is contained in:
2026-07-17 00:04:30 +03:00
parent d985a3d122
commit cbd65ed7db
3 changed files with 86 additions and 5 deletions
+22 -1
View File
@@ -719,7 +719,15 @@ const TICKER_COLORS_LIGHT = [
'#3498db', '#1abc9c', '#b8860b', '#8e44ad', '#e74c3c'
];
const isLightTheme = window.matchMedia('(prefers-color-scheme: light)').matches;
const THEME_KEY = 'numnum-theme';
function getPreferredTheme() {
const saved = localStorage.getItem(THEME_KEY);
if (saved === 'light' || saved === 'dark') return saved;
return window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark';
}
const isLightTheme = getPreferredTheme() === 'light';
const TICKER_COLORS = isLightTheme ? TICKER_COLORS_LIGHT : TICKER_COLORS_DARK;
const TICKER_SYSTEMS = [
@@ -776,6 +784,19 @@ langSelect.addEventListener('change', () => {
applyTranslations();
function applyTheme(theme) {
document.documentElement.dataset.theme = theme;
document.getElementById('theme-toggle').textContent = theme === 'dark' ? '\u2600' : '\u263E';
}
applyTheme(getPreferredTheme());
document.getElementById('theme-toggle').addEventListener('click', () => {
const next = document.documentElement.dataset.theme === 'dark' ? 'light' : 'dark';
localStorage.setItem(THEME_KEY, next);
applyTheme(next);
});
let deferredPrompt = null;
window.addEventListener('beforeinstallprompt', (e) => {
+7 -4
View File
@@ -24,10 +24,13 @@
<div class="ticker" id="ticker"></div>
</div>
<button class="btn btn-primary btn-large" id="btn-start" data-i18n="startGame">Start Game</button>
<select id="lang-select" class="lang-select">
<option value="en">English</option>
<option value="ru">Русский</option>
</select>
<div class="menu-controls">
<select id="lang-select" class="lang-select">
<option value="en">English</option>
<option value="ru">Русский</option>
</select>
<button id="theme-toggle" class="theme-toggle" aria-label="Toggle theme"></button>
</div>
<button class="btn btn-secondary btn-large hidden" id="btn-install" data-i18n="installApp">Install App</button>
</div>
</div>
+57
View File
@@ -37,6 +37,34 @@
}
}
html[data-theme="dark"] {
--bg: #1a1a2e;
--bg-light: #16213e;
--bg-card: #0f3460;
--accent: #e94560;
--accent-hover: #ff6b81;
--accent-secondary: #ff9a56;
--text: #eaeaea;
--text-dim: #a0a0b0;
--correct: #2ecc71;
--incorrect: #e74c3c;
--border: rgba(255,255,255,0.08);
}
html[data-theme="light"] {
--bg: #f5f5f5;
--bg-light: #ffffff;
--bg-card: #ffffff;
--accent: #e94560;
--accent-hover: #d63851;
--accent-secondary: #f09040;
--text: #1a1a2e;
--text-dim: #555566;
--correct: #27ae60;
--incorrect: #c0392b;
--border: #d0d0d0;
}
@font-face {
font-family: 'Ponomar';
src: url('Ponomar-Regular.woff') format('woff');
@@ -127,6 +155,35 @@ body {
display: block;
}
.menu-controls {
display: flex;
gap: 8px;
width: 100%;
max-width: 320px;
}
.menu-controls .lang-select {
flex: 1;
width: auto;
max-width: none;
margin: 0;
}
.theme-toggle {
width: 44px;
height: 44px;
flex-shrink: 0;
background: var(--bg-light);
color: var(--text);
border: 2px solid var(--border);
border-radius: 8px;
font-size: 1.3rem;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
.ticker {
display: inline-block;
white-space: nowrap;