Skip to content

Commit 42a2197

Browse files
committed
add system theme mode
1 parent decd214 commit 42a2197

File tree

1 file changed

+34
-9
lines changed

1 file changed

+34
-9
lines changed

src/components/SiteNav.astro

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,27 +42,52 @@
4242
class="flex items-center gap-2 bg-transparent border-[1.5px] border-fg text-fg px-4 py-[0.45rem] font-sans text-[0.8125rem] font-medium tracking-widest uppercase cursor-pointer transition-colors duration-200 hover:bg-fg hover:text-bg"
4343
>
4444
<span aria-hidden="true" class="text-[0.9rem] leading-none">◐</span>
45-
<span id="theme-label">Dark mode</span>
45+
<span id="theme-label">System mode</span>
4646
</button>
4747
</div>
4848
</nav>
4949

5050
<script>
51+
const MODES = ['system', 'light', 'dark'] as const;
52+
type Mode = (typeof MODES)[number];
53+
5154
const toggle = document.getElementById('theme-toggle');
5255
const label = document.getElementById('theme-label');
5356
const html = document.documentElement;
5457

55-
function applyTheme(theme: string) {
56-
html.setAttribute('data-theme', theme);
57-
if (label) label.textContent = theme === 'dark' ? 'Light mode' : 'Dark mode';
58+
const modeLabels: Record<Mode, string> = {
59+
system: 'System mode',
60+
light: 'Light mode',
61+
dark: 'Dark mode',
62+
};
63+
64+
function getStoredMode(): Mode {
65+
const saved = localStorage.getItem('theme');
66+
if (saved === 'light' || saved === 'dark') return saved;
67+
return 'system';
68+
}
69+
70+
function applyMode(mode: Mode) {
71+
if (mode === 'system') {
72+
localStorage.removeItem('theme');
73+
const sys = window.matchMedia('(prefers-color-scheme: dark)').matches
74+
? 'dark'
75+
: 'light';
76+
html.setAttribute('data-theme', sys);
77+
} else {
78+
localStorage.setItem('theme', mode);
79+
html.setAttribute('data-theme', mode);
80+
}
81+
if (label) label.textContent = modeLabels[mode];
5882
}
5983

60-
const current = html.getAttribute('data-theme') || 'light';
61-
if (label) label.textContent = current === 'dark' ? 'Light mode' : 'Dark mode';
84+
let currentMode: Mode = getStoredMode();
85+
// Set label on init; theme is already applied by the no-flash inline script
86+
if (label) label.textContent = modeLabels[currentMode];
6287

6388
toggle?.addEventListener('click', () => {
64-
const next = html.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
65-
applyTheme(next);
66-
localStorage.setItem('theme', next);
89+
const idx = MODES.indexOf(currentMode);
90+
currentMode = MODES[(idx + 1) % MODES.length];
91+
applyMode(currentMode);
6792
});
6893
</script>

0 commit comments

Comments
 (0)