diff --git a/docs/site.js b/docs/site.js index 519d359..95672c7 100644 --- a/docs/site.js +++ b/docs/site.js @@ -2,9 +2,9 @@ const themeButtons = document.querySelectorAll("[data-theme-toggle]"); const themeStorageKey = "pi-web-theme"; const systemPrefersLight = window.matchMedia("(prefers-color-scheme: light)"); -function storedTheme() { +function storedThemeMode() { const theme = window.localStorage.getItem(themeStorageKey); - return theme === "light" || theme === "dark" ? theme : undefined; + return theme === "light" || theme === "dark" || theme === "auto" ? theme : "auto"; } function activeTheme() { @@ -15,28 +15,49 @@ function activeTheme() { : "dark"; } -function updateThemeButtons(theme = activeTheme()) { +function applyThemeMode(mode) { + if (mode === "light" || mode === "dark") { + document.documentElement.dataset.theme = mode; + } else { + delete document.documentElement.dataset.theme; + } + window.localStorage.setItem(themeStorageKey, mode); + updateThemeButtons(mode); +} + +function updateThemeButtons(mode = storedThemeMode()) { + const active = activeTheme(); for (const button of themeButtons) { - button.dataset.theme = theme; - button.setAttribute("aria-pressed", theme === "light" ? "true" : "false"); + button.dataset.theme = mode; + button.dataset.activeTheme = active; const icon = button.querySelector("[data-theme-icon]"); const label = button.querySelector("[data-theme-label]"); - if (icon !== null) icon.textContent = theme === "light" ? "☀" : "☾"; - if (label !== null) label.textContent = theme === "light" ? "Light" : "Dark"; + if (mode === "auto") { + button.setAttribute("aria-label", `Theme: Auto (${active}). Click to use dark theme.`); + if (icon !== null) icon.textContent = "◐"; + if (label !== null) label.textContent = "Auto"; + } else if (mode === "light") { + button.setAttribute("aria-label", "Theme: Light. Click to use automatic theme."); + if (icon !== null) icon.textContent = "☀"; + if (label !== null) label.textContent = "Light"; + } else { + button.setAttribute("aria-label", "Theme: Dark. Click to use light theme."); + if (icon !== null) icon.textContent = "☾"; + if (label !== null) label.textContent = "Dark"; + } } } updateThemeButtons(); systemPrefersLight.addEventListener("change", () => { - if (storedTheme() === undefined) updateThemeButtons(); + if (storedThemeMode() === "auto") updateThemeButtons("auto"); }); for (const button of themeButtons) { button.addEventListener("click", () => { - const nextTheme = activeTheme() === "light" ? "dark" : "light"; - document.documentElement.dataset.theme = nextTheme; - window.localStorage.setItem(themeStorageKey, nextTheme); - updateThemeButtons(nextTheme); + const currentMode = storedThemeMode(); + const nextTheme = currentMode === "auto" ? "dark" : currentMode === "dark" ? "light" : "auto"; + applyThemeMode(nextTheme); }); } diff --git a/docs/styles.css b/docs/styles.css index cc0b27c..c8154ad 100644 --- a/docs/styles.css +++ b/docs/styles.css @@ -65,7 +65,7 @@ body::after { display: inline-block; opacity: 0; transform: translateY(-42vh); - animation: word-drop 640ms cubic-bezier(0.18, 0.88, 0.22, 1.08) forwards; + animation: word-drop 520ms cubic-bezier(0.34, 0, 0.2, 1) forwards; animation-delay: calc(140ms + (var(--i) * 190ms)); color: var(--intro-color, var(--text)); } @@ -96,11 +96,6 @@ body::after { transform: translateY(-42vh); } - 72% { - opacity: 1; - transform: translateY(0.08em); - } - 100% { opacity: 1; transform: translateY(0); @@ -199,7 +194,8 @@ video { display: inline-flex; align-items: center; gap: 8px; - padding: 10px 12px; + min-height: 42px; + padding: 0 12px; border: 1px solid transparent; } @@ -218,12 +214,26 @@ video { } .theme-toggle { + width: 92px; + justify-content: center; + appearance: none; + line-height: 1; background: transparent; color: var(--muted); font: inherit; cursor: pointer; } +.theme-toggle [data-theme-icon], +.theme-toggle [data-theme-label] { + display: inline-block; + line-height: 1; +} + +.theme-toggle[data-theme="auto"] [data-theme-icon] { + color: var(--brand); +} + .theme-toggle[data-theme="dark"] [data-theme-icon] { color: var(--brand-2); }