diff --git a/static/demos/light-dark-superior_v1/index.html b/static/demos/light-dark-superior_v1/index.html new file mode 100644 index 0000000..fe39f92 --- /dev/null +++ b/static/demos/light-dark-superior_v1/index.html @@ -0,0 +1,48 @@ + + + +
+ + + + + + + + +Light and/or dark theming is only applicable if you have CSS, if you see this then either the CSS + hasn't loaded yet or your user agent doesn't support CSS
+ +Hello this is some text, should be black on white background if you're light theme and white on black background + if you're dark theme
+ + + diff --git a/static/demos/light-dark-superior_v1/script.js b/static/demos/light-dark-superior_v1/script.js new file mode 100644 index 0000000..59135ab --- /dev/null +++ b/static/demos/light-dark-superior_v1/script.js @@ -0,0 +1,44 @@ +"use strict"; + +const toggle_button = document.body.querySelector("#light_dark_toggle"); +const css_state_checkbox = document.body.querySelector("#css_state"); + +// this does nothing but I was hoping it would let my LSP figure out +// that css_state_checkbox is an input element so the remaining code +// is valid +// Real use case might still find this useful as self documenting code +console.assert(css_state_checkbox instanceof HTMLInputElement); + +toggle_button.addEventListener("click", (event) => { + + // js will handle the needed logic so no need for a HTTP form submission + event.preventDefault(); + + + const theme_toggled = !css_state_checkbox.checked; + + // set the cookie so backend/service worker can do it's thing + // cookies have other options you may wanna set especially + // if you're using them for anything else but for this + // use case I see no reason to care + document.cookie = `theme_toggled=${theme_toggled}`; + + + css_state_checkbox.checked = theme_toggled; +}); + +// If you wanna implement this for a site with a backend +// then feel free to ignore everything below I need it because +// I'm using github pages to host this rather than a proper +// backend +if (!("serviceWorker" in navigator)) { + alert("Your browser doesn't support service workers so this demo won't work properly."); + +} +else setupServiceWorker(); +async function setupServiceWorker() { + await navigator.serviceWorker.register("sw.js", { + // we only need to interact with index.html for this demo + scope: "./index.html" + }); +} diff --git a/static/demos/light-dark-superior_v1/style.css b/static/demos/light-dark-superior_v1/style.css new file mode 100644 index 0000000..f4c02b5 --- /dev/null +++ b/static/demos/light-dark-superior_v1/style.css @@ -0,0 +1,35 @@ +.hide { + display: none; +} + +@media (prefers-color-scheme: dark){ + :root { + --background-color: black; + --text-color: white; + } + :root:has(#css_state:checked){ + --background-color: white; + --text-color: black; + } +} +@media (prefers-color-scheme: light){ + :root { + --background-color: white; + --text-color: black; + } + :root:has(#css_state:checked){ + --background-color: black; + --text-color: white; + } +} + +p { + color: var(--text-color); +} +body { + background: var(--background-color); +} + +#light_dark_toggle{ + display:block; +} diff --git a/static/demos/light-dark-superior_v1/sw.js b/static/demos/light-dark-superior_v1/sw.js new file mode 100644 index 0000000..b8ce162 --- /dev/null +++ b/static/demos/light-dark-superior_v1/sw.js @@ -0,0 +1,28 @@ +"use strict"; + +// @returns Response +// https://developer.mozilla.org/en-US/docs/Web/API/Response +async function fetchResponse(event) { + //https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent/request + //https://developer.mozilla.org/en-US/docs/Web/API/Request + const { request } = event; + const resp = await fetch(request); + const body = await resp.text(); + const cookies = resp.headers.getSetCookie(); + let theme_toggled = false; + for (let cookie of cookies) { + const [key, value] = cookie.split("="); + if (key != "theme_toggled") { + continue; + } + theme_toggled = value[0] === "t"; + } + // this is a brittle way of accomplishing our desired behavior + body.replace(``, + ``) +} + +self.addEventListener('fetch', (event) => { + //https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent/respondWith + event.respondWith(fetchResponse(event)); +})