Files
tsuki/assets/js/theme-toggle.js
T
tiennm99 e19bb67c88 feat: visual layer with vi typography, dark mode, view transitions (Phase 6)
- 9 CSS files (tokens, reset, typography, layout, components, home,
  archive, toc, view-transitions) bundled via resources.Concat
- 3 ES module JS files (theme-toggle, code-copy, toc-active); toc-active
  loaded only on long posts
- @view-transition: navigation auto for cross-page morph (CSS-only)
- TOC partial gated by WordCount>400 and Params.toc!=false; sticky on
  wide viewports, framed block on narrow
- render-heading.html adds cosmetic anchor links
- Hugo asset pipeline: resources.Concat | minify | fingerprint (no
  SCSS, no PostCSS, no Node)
- i18n/vi.yml extended with prev/next/posts/archiveEmpty/toggleTheme
- Bundle sizes: CSS 3.3 KB gz (budget 15), JS 0.8 KB gz (budget 8)

Config: github-ascii heading IDs, :contentbasename permalink token for
clean ASCII URLs, pagination.pagerSize migration (Hugo 0.128+).
2026-05-07 21:27:46 +07:00

22 lines
845 B
JavaScript

const KEY = "tsuki-theme";
const root = document.documentElement;
const btn = document.querySelector("[data-theme-toggle]");
if (btn) {
btn.hidden = false;
btn.addEventListener("click", () => {
const explicit = root.getAttribute("data-theme");
const current = explicit
|| (matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light");
const next = current === "dark" ? "light" : "dark";
root.setAttribute("data-theme", next);
try { localStorage.setItem(KEY, next); } catch {}
btn.setAttribute("aria-pressed", String(next === "dark"));
});
const stored = (() => { try { return localStorage.getItem(KEY); } catch { return null; } })();
const isDark = stored === "dark"
|| (!stored && matchMedia("(prefers-color-scheme: dark)").matches);
btn.setAttribute("aria-pressed", String(isDark));
}