Respect system theme on website

This commit is contained in:
KoalaDev
2026-07-09 14:38:09 +02:00
parent 1d049e1745
commit e25ae25bbb
3 changed files with 62 additions and 17 deletions
+32 -10
View File
@@ -60,19 +60,29 @@ document.addEventListener('DOMContentLoaded', () => {
}
};
// Theme toggle (dark is default; light mode via html.theme-light,
// Theme toggle (saved preference wins; otherwise follows system preference,
// pre-paint class is applied by lang-init.js to avoid a flash)
const themeToggle = document.getElementById('theme-toggle');
const themeMeta = document.querySelector('meta[name="theme-color"]');
const themeStorageKey = 'koala_theme';
const systemThemeQuery = (() => {
try {
return window.matchMedia ? window.matchMedia('(prefers-color-scheme: light)') : null;
} catch (_) {
return null;
}
})();
const getSystemTheme = () => systemThemeQuery && systemThemeQuery.matches ? 'light' : 'dark';
const getSavedTheme = () => {
const savedTheme = safeGetLocalStorage(themeStorageKey);
return savedTheme === 'light' || savedTheme === 'dark' ? savedTheme : null;
};
const getCurrentTheme = () => document.documentElement.classList.contains('theme-light') ? 'light' : 'dark';
const savedTheme = safeGetLocalStorage(themeStorageKey);
const applyTheme = (theme) => {
document.documentElement.classList.toggle('theme-light', theme === 'light');
};
if (savedTheme === 'light') {
document.documentElement.classList.add('theme-light');
} else if (savedTheme === 'dark') {
document.documentElement.classList.remove('theme-light');
}
applyTheme(getSavedTheme() || getSystemTheme());
const syncThemeMeta = () => {
if (themeMeta) {
@@ -80,11 +90,23 @@ document.addEventListener('DOMContentLoaded', () => {
}
};
syncThemeMeta();
safeSetLocalStorage(themeStorageKey, getCurrentTheme());
const syncSystemTheme = () => {
if (getSavedTheme()) return;
applyTheme(getSystemTheme());
syncThemeMeta();
};
if (systemThemeQuery) {
if (typeof systemThemeQuery.addEventListener === 'function') {
systemThemeQuery.addEventListener('change', syncSystemTheme);
} else if (typeof systemThemeQuery.addListener === 'function') {
systemThemeQuery.addListener(syncSystemTheme);
}
}
if (themeToggle) {
themeToggle.addEventListener('click', () => {
const isLight = document.documentElement.classList.toggle('theme-light');
safeSetLocalStorage(themeStorageKey, isLight ? 'light' : 'dark');
const nextTheme = getCurrentTheme() === 'light' ? 'dark' : 'light';
applyTheme(nextTheme);
safeSetLocalStorage(themeStorageKey, nextTheme);
syncThemeMeta();
});
}
+15 -5
View File
@@ -57,6 +57,10 @@
</a>
</div>
<div class="nav-right">
<button class="theme-toggle" id="theme-toggle" type="button" aria-label="Toggle light/dark mode" title="Toggle light/dark mode">
<svg class="theme-icon-sun" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="18" height="18" aria-hidden="true"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41"/></svg>
<svg class="theme-icon-moon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="18" height="18" aria-hidden="true"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/></svg>
</button>
<div class="lang-select-container">
<select class="lang-dropdown" aria-label="Select Language">
<option value="en">🇬🇧 English</option>
@@ -115,13 +119,19 @@
<footer>
<div class="container">
<p>&copy; 2026 KoalaSync. Open source under the MIT License.</p>
<p lang="en" style="font-size: 0.8rem; margin-top: 0.5rem;">No relay logs. No tracking. Website access logs are deleted after 7 days.</p>
<p lang="de" style="font-size: 0.8rem; margin-top: 0.5rem;">Keine Relay-Logs. Kein Tracking. Website-Access-Logs werden nach 7 Tagen gelöscht.</p>
<p>&copy; 2026 KoalaSync. <span lang="en">Open source under the MIT License.</span><span lang="de">Open Source unter der MIT-Lizenz.</span></p>
<p style="font-size: 0.8rem; margin-top: 0.5rem;"><span lang="en">No relay logs. No tracking. Website access logs are deleted after 7 days.</span><span lang="de">Keine Relay-Logs. Kein Tracking. Website-Access-Logs werden nach 7 Tagen gelöscht.</span></p>
<p style="font-size: 0.72rem; margin-top: 1.2rem; color: var(--text-muted); opacity: 0.65; max-width: 650px; margin-left: auto; margin-right: auto; line-height: 1.5;"><span lang="en">KoalaSync is not affiliated with, endorsed by, or associated with Netflix, Disney+, Amazon, YouTube, Twitch, or any other streaming platform. All trademarks are property of their respective owners.</span><span lang="de">KoalaSync ist nicht mit Netflix, Disney+, Amazon, YouTube, Twitch oder anderen Streaming-Plattformen verbunden, wird von diesen nicht unterstützt oder steht in keiner Beziehung zu diesen. Alle Markenrechte liegen bei ihren jeweiligen Inhabern.</span></p>
<div style="margin-top: 1.5rem; font-size: 0.8rem; display: flex; justify-content: center; align-items: center; gap: 1.5rem; flex-wrap: wrap;">
<a href="impressum" style="color: var(--text-muted); text-decoration: none;"><span lang="en">Legal Notice</span><span lang="de">Impressum</span></a>
<a href="datenschutz" style="color: var(--text-muted); text-decoration: none;"><span lang="en">Privacy Policy</span><span lang="de">Datenschutz</span></a>
<a href="imprint" lang="en" style="color: var(--text-muted); text-decoration: none;">Legal Notice</a>
<a href="de/impressum" lang="de" style="color: var(--text-muted); text-decoration: none;">Impressum</a>
<a href="privacy" lang="en" style="color: var(--text-muted); text-decoration: none;">Privacy Policy</a>
<a href="de/datenschutz" lang="de" style="color: var(--text-muted); text-decoration: none;">Datenschutz</a>
<a href="alternatives"><span lang="en">Guides & comparisons</span><span lang="de">Vergleiche & Anleitungen</span></a>
<a href="https://support.koalastuff.net" target="_blank" rel="noopener" title="Support KoalaSync" style="color: #fff; text-decoration: none; display: inline-flex; align-items: center; gap: 6px; background: #c9302c; border: 1px solid rgba(255,255,255,0.18); border-radius: 999px; padding: 3px 9px; font-size: 0.72rem; font-weight: 700; line-height: 1;">
<span aria-hidden="true"></span>
<span>Support KoalaSync</span>
</a>
<a href="https://mastodon.social/@koalastuff" rel="me noopener" target="_blank" style="color: var(--text-muted); text-decoration: none; display: inline-flex; align-items: center; gap: 4px;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" width="14" height="14" aria-hidden="true" style="display: block;"><path d="M23.268 5.313c-.35-2.578-2.617-4.61-5.304-5.004C17.51.242 15.792 0 11.813 0h-.03c-3.98 0-4.835.242-5.288.309C3.882.692 1.496 2.518.917 5.127.64 6.412.61 7.837.661 9.143c.074 1.874.088 3.745.26 5.611.118 1.24.325 2.47.62 3.68.55 2.237 2.777 4.098 4.96 4.857 2.336.792 4.849.923 7.256.38.265-.061.527-.132.786-.213.585-.184 1.27-.39 1.774-.753a.057.057 0 0 0 .023-.043v-1.809a.052.052 0 0 0-.02-.041.053.053 0 0 0-.046-.01 20.282 20.282 0 0 1-4.709.545c-2.73 0-3.463-1.284-3.674-1.818a5.593 5.593 0 0 1-.319-1.433.053.053 0 0 1 .066-.054c1.517.363 3.072.546 4.632.546.376 0 .75 0 1.125-.01 1.57-.044 3.224-.124 4.768-.422.038-.008.077-.015.11-.024 2.435-.464 4.753-1.92 4.989-5.604.008-.145.03-1.52.03-1.67.002-.512.167-3.63-.024-5.545zm-3.748 9.195h-2.561V8.29c0-1.309-.55-1.976-1.67-1.976-1.23 0-1.846.79-1.846 2.35v3.403h-2.546V8.663c0-1.56-.617-2.35-1.848-2.35-1.112 0-1.668.668-1.67 1.977v6.218H4.822V8.102c0-1.31.337-2.35 1.011-3.12.696-.77 1.608-1.164 2.74-1.164 1.311 0 2.302.5 2.962 1.498l.638 1.06.638-1.06c.66-.999 1.65-1.498 2.96-1.498 1.13 0 2.043.395 2.74 1.164.675.77 1.012 1.81 1.012 3.12z"/></svg>
Mastodon
+15 -2
View File
@@ -18,9 +18,22 @@
}
};
// Apply saved theme before first paint (dark is the default, no class needed)
if (safeGetLocalStorage('koala_theme') === 'light') {
var getSystemTheme = function() {
try {
return window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark';
} catch (_) {
return 'dark';
}
};
// Apply the effective theme before first paint. A saved preference wins;
// otherwise first-time visitors follow their browser/system setting.
var savedTheme = safeGetLocalStorage('koala_theme');
var effectiveTheme = savedTheme === 'light' || savedTheme === 'dark' ? savedTheme : getSystemTheme();
if (effectiveTheme === 'light') {
html.classList.add('theme-light');
} else {
html.classList.remove('theme-light');
}
// Mapping of browser language codes to KoalaSync locale directories