began work on light-dark demo
This commit is contained in:
parent
0041aecea1
commit
9429da6221
4 changed files with 155 additions and 0 deletions
48
static/demos/light-dark-superior_v1/index.html
Normal file
48
static/demos/light-dark-superior_v1/index.html
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<link rel="stylesheet" href="style.css" type="text/css">
|
||||||
|
<script type="module" src="script.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<!--
|
||||||
|
in the context of github pages where we have no
|
||||||
|
backend the form element is for demonstration
|
||||||
|
rather than actual function in the demo
|
||||||
|
in an implementation with a proper backend the
|
||||||
|
form element would allow for the toggle button
|
||||||
|
to work without Javascript
|
||||||
|
-->
|
||||||
|
<form action="" method="post">
|
||||||
|
<!--
|
||||||
|
id present so service worker shenanigans are
|
||||||
|
more durable and css has something to latch
|
||||||
|
onto
|
||||||
|
|
||||||
|
hidden because the user should never see this
|
||||||
|
checkbox
|
||||||
|
-->
|
||||||
|
<input id="css_state" type="checkbox" hidden>
|
||||||
|
<!--
|
||||||
|
hidden because if a user agent doesn't support
|
||||||
|
CSS we don't want to show the light-dark toggle
|
||||||
|
|
||||||
|
id present so the css can make it visible again and js can grab it
|
||||||
|
-->
|
||||||
|
<input id="light_dark_toggle" type="submit" value="Toggle light/dark theme" hidden>
|
||||||
|
</form>
|
||||||
|
<p class="hide">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</p>
|
||||||
|
<noscript>
|
||||||
|
<p>While an implementation with a proper backened wouldn't need javascript this demo does due to being hosted on
|
||||||
|
github pages. Specifically the javascript is needed to create a service worker to do the work a backend
|
||||||
|
would be doing otherwise.</p>
|
||||||
|
</noscript>
|
||||||
|
<p>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</p>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
44
static/demos/light-dark-superior_v1/script.js
Normal file
44
static/demos/light-dark-superior_v1/script.js
Normal file
|
@ -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"
|
||||||
|
});
|
||||||
|
}
|
35
static/demos/light-dark-superior_v1/style.css
Normal file
35
static/demos/light-dark-superior_v1/style.css
Normal file
|
@ -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;
|
||||||
|
}
|
28
static/demos/light-dark-superior_v1/sw.js
Normal file
28
static/demos/light-dark-superior_v1/sw.js
Normal file
|
@ -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(`<input id="css_state" type="checkbox" hidden>`,
|
||||||
|
`<input id="css_state" type="checkbox" hidden ${theme_toggled ? "checked" : ""}>`)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.addEventListener('fetch', (event) => {
|
||||||
|
//https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent/respondWith
|
||||||
|
event.respondWith(fetchResponse(event));
|
||||||
|
})
|
Loading…
Reference in a new issue