Honor user's preference for light/dark mode.

This commit is contained in:
2026-07-26 22:00:53 +02:00
parent a5f1b1ead3
commit c5cff94d5a
3 changed files with 43 additions and 13 deletions
+15 -9
View File
@@ -1,20 +1,26 @@
(() => { (() => {
const root = document.documentElement; const root = document.documentElement;
const colorModes = ['auto', 'light', 'dark'];
const storedTheme = localStorage.getItem('c1024-theme'); const storedTheme = localStorage.getItem('c1024-theme');
if (storedTheme) root.dataset.theme = storedTheme; let colorMode = colorModes.includes(storedTheme) ? storedTheme : 'auto';
root.dataset.theme = colorMode;
const themeToggle = document.querySelector('[data-theme-toggle]'); const themeToggle = document.querySelector('[data-theme-toggle]');
if (themeToggle) { if (themeToggle) {
const updateThemeLabel = () => { const themeIcon = themeToggle.querySelector('[data-theme-icon]');
const dark = root.dataset.theme === 'dark'; const labels = { auto: 'Automatic', light: 'Light', dark: 'Dark' };
themeToggle.setAttribute('aria-pressed', String(dark)); const icons = { auto: '#icon-auto', light: '#icon-light', dark: '#icon-dark' };
themeToggle.setAttribute('aria-label', dark ? 'Use light mode' : 'Use dark mode'); const updateThemeControl = () => {
const nextMode = colorModes[(colorModes.indexOf(colorMode) + 1) % colorModes.length];
themeToggle.setAttribute('aria-label', `Color mode: ${labels[colorMode]}. Activate to use ${labels[nextMode]} mode.`);
themeIcon.setAttribute('href', icons[colorMode]);
}; };
updateThemeLabel(); updateThemeControl();
themeToggle.addEventListener('click', () => { themeToggle.addEventListener('click', () => {
root.dataset.theme = root.dataset.theme === 'dark' ? 'light' : 'dark'; colorMode = colorModes[(colorModes.indexOf(colorMode) + 1) % colorModes.length];
localStorage.setItem('c1024-theme', root.dataset.theme); root.dataset.theme = colorMode;
updateThemeLabel(); localStorage.setItem('c1024-theme', colorMode);
updateThemeControl();
}); });
} }
+2 -2
View File
@@ -22,9 +22,9 @@
</nav> </nav>
<div class="header-actions"> <div class="header-actions">
<button class="icon-button" type="button" data-search-toggle aria-expanded="false" aria-controls="site-search"><span class="screen-reader-text"><?php esc_html_e( 'Open search', 'c1024-2026' ); ?></span><svg class="icon" aria-hidden="true"><use href="#icon-search"></use></svg></button> <button class="icon-button" type="button" data-search-toggle aria-expanded="false" aria-controls="site-search"><span class="screen-reader-text"><?php esc_html_e( 'Open search', 'c1024-2026' ); ?></span><svg class="icon" aria-hidden="true"><use href="#icon-search"></use></svg></button>
<button class="icon-button" type="button" data-theme-toggle aria-pressed="false"><span class="screen-reader-text"><?php esc_html_e( 'Change color mode', 'c1024-2026' ); ?></span><svg class="icon" aria-hidden="true"><use href="#icon-theme"></use></svg></button> <button class="icon-button" type="button" data-theme-toggle><span class="screen-reader-text"><?php esc_html_e( 'Change color mode', 'c1024-2026' ); ?></span><svg class="icon" aria-hidden="true"><use data-theme-icon href="#icon-auto"></use></svg></button>
</div> </div>
</div> </div>
<div class="search-panel" id="site-search" data-search-panel><?php get_search_form(); ?></div> <div class="search-panel" id="site-search" data-search-panel><?php get_search_form(); ?></div>
</header> </header>
<svg width="0" height="0" class="screen-reader-text" aria-hidden="true"><symbol id="icon-search" viewBox="0 0 24 24"><circle cx="10.8" cy="10.8" r="6.5"></circle><path d="m16 16 5 5"></path></symbol><symbol id="icon-theme" viewBox="0 0 24 24"><circle cx="12" cy="12" r="4"></circle><path d="M12 2v2m0 16v2M2 12h2m16 0h2M4.9 4.9l1.4 1.4m11.4 11.4 1.4 1.4m0-14.2-1.4 1.4M6.3 17.7l-1.4 1.4"></path></symbol><symbol id="icon-menu" viewBox="0 0 24 24"><path d="M3 6h18M3 12h18M3 18h18"></path></symbol></svg> <svg width="0" height="0" class="screen-reader-text" aria-hidden="true"><symbol id="icon-search" viewBox="0 0 24 24"><circle cx="10.8" cy="10.8" r="6.5"></circle><path d="m16 16 5 5"></path></symbol><symbol id="icon-light" viewBox="0 0 24 24"><circle cx="12" cy="12" r="4"></circle><path d="M12 2v2m0 16v2M2 12h2m16 0h2M4.9 4.9l1.4 1.4m11.4 11.4 1.4 1.4m0-14.2-1.4 1.4M6.3 17.7l-1.4 1.4"></path></symbol><symbol id="icon-dark" viewBox="0 0 24 24"><path d="M20 15.2A8.5 8.5 0 0 1 8.8 4 8.5 8.5 0 1 0 20 15.2Z"></path></symbol><symbol id="icon-auto" viewBox="0 0 24 24"><circle cx="12" cy="12" r="7"></circle><path d="M12 2v2m0 16v2M2 12h2m16 0h2M5 5l1.4 1.4m11.2 11.2L19 19m0-14-1.4 1.4M6.4 17.6 5 19M9.5 15l2.5-6 2.5 6m-4-2h3"></path></symbol><symbol id="icon-menu" viewBox="0 0 24 24"><path d="M3 6h18M3 12h18M3 18h18"></path></symbol></svg>
+26 -2
View File
@@ -73,6 +73,22 @@ License URI: https://www.gnu.org/licenses/gpl-2.0.html
--code-text: #f5eee5; --code-text: #f5eee5;
--shadow: 0 10px 30px rgba(0, 0, 0, 0.25); --shadow: 0 10px 30px rgba(0, 0, 0, 0.25);
} }
@media (prefers-color-scheme: dark) {
:root:not([data-theme]),
:root[data-theme="auto"] {
color-scheme: dark;
--bg: #171615;
--surface: #22201e;
--text: #eee8e1;
--muted: #b9afa5;
--line: #4a4540;
--accent: #f07a3c;
--accent-hover: #ff9d6a;
--code-bg: #0e0e0d;
--code-text: #f5eee5;
--shadow: 0 10px 30px rgba(0, 0, 0, 0.25);
}
}
* { * {
box-sizing: border-box; box-sizing: border-box;
} }
@@ -183,7 +199,7 @@ button {
margin: 0.1rem 0 0; margin: 0.1rem 0 0;
color: var(--muted); color: var(--muted);
font-family: "Berkeley Mono", monospace; font-family: "Berkeley Mono", monospace;
font-size: 0.64rem; font-size: 1rem;
letter-spacing: 0.07em; letter-spacing: 0.07em;
} }
.primary-menu { .primary-menu {
@@ -194,7 +210,7 @@ button {
padding: 0; padding: 0;
list-style: none; list-style: none;
font-family: "Berkeley Mono", monospace; font-family: "Berkeley Mono", monospace;
font-size: 0.7rem; font-size: 1rem;
letter-spacing: 0.04em; letter-spacing: 0.04em;
} }
.primary-menu a { .primary-menu a {
@@ -742,6 +758,14 @@ h4 {
.primary-menu > li.menu-item-has-children > a::after { .primary-menu > li.menu-item-has-children > a::after {
vertical-align: -0.2em; vertical-align: -0.2em;
} }
body.admin-bar .site-header {
top: 32px;
}
@media (max-width: 782px) {
body.admin-bar .site-header {
top: 46px;
}
}
@media (prefers-reduced-motion: reduce) { @media (prefers-reduced-motion: reduce) {
*, *,
*::before, *::before,