diff --git a/index.html b/index.html index ca20e5e..9c4dc3b 100644 --- a/index.html +++ b/index.html @@ -3,7 +3,7 @@ - +
+ +
🚂 @@ -273,15 +406,26 @@
- +
+ + +
0 trains dispatched
@@ -297,8 +441,10 @@ const dispatcher = document.querySelector("#dispatcher"); const hero = document.querySelector("#hero"); + const themeButton = document.querySelector("#theme"); const muteButton = document.querySelector("#mute"); const counter = document.querySelector("#counter"); + const themeMeta = document.querySelector('meta[name="theme-color"]'); const choo = new Audio("./public/choo-choo.mp3"); choo.preload = "auto"; @@ -308,6 +454,9 @@ let lastLane = -1; let lastDirection = "rtl"; let muted = localStorage.getItem("wtc:muted") === "1"; + let theme = + localStorage.getItem("wtc:theme") || + (window.matchMedia("(prefers-color-scheme: dark)").matches ? "night" : "day"); function pick(items) { return items[Math.floor(Math.random() * items.length)]; @@ -320,6 +469,19 @@ localStorage.setItem("wtc:muted", muted ? "1" : "0"); } + function syncThemeButton() { + const isNight = theme === "night"; + document.documentElement.dataset.theme = theme; + themeButton.textContent = isNight ? "☀️" : "🌙"; + themeButton.setAttribute( + "aria-label", + isNight ? "Use day mode" : "Use night mode", + ); + themeButton.setAttribute("aria-pressed", String(isNight)); + themeMeta.setAttribute("content", isNight ? "#09111f" : "#fbfbfa"); + localStorage.setItem("wtc:theme", theme); + } + function updateCounter() { const noun = count === 1 ? "train" : "trains"; counter.textContent = `${count} ${noun} dispatched`; @@ -404,16 +566,33 @@ syncMuteButton(); }); + themeButton.addEventListener("click", (event) => { + event.stopPropagation(); + theme = theme === "night" ? "day" : "night"; + syncThemeButton(); + }); + window.addEventListener("keydown", (event) => { + const isButtonKey = + (event.code === "Space" || event.code === "Enter") && + event.target instanceof HTMLElement && + event.target.closest("button"); + + if (isButtonKey) return; + if (event.code === "Space" || event.code === "Enter") { event.preventDefault(); dispatchTrain(); } else if (event.key === "m" || event.key === "M") { muted = !muted; syncMuteButton(); + } else if (event.key === "n" || event.key === "N") { + theme = theme === "night" ? "day" : "night"; + syncThemeButton(); } }); + syncThemeButton(); syncMuteButton(); updateCounter();