diff --git a/lightdark.py b/lightdark.py new file mode 100644 index 0000000..de65ade --- /dev/null +++ b/lightdark.py @@ -0,0 +1,103 @@ +from fasthtml.common import * + + +def atag(theme="auto"): + return A(href="#", data_theme_switcher=theme) + + +def AutoLink(*inner): + return atag("auto")(*inner) + + +def DarkLink(*inner): + return atag("dark")(*inner) + + +def LightLink(*inner): + return atag("light")(*inner) + + +def LightDarkScript(): + return Script( + """ +/*! + * Minimal theme switcher + * + * Pico.css - https://picocss.com + * Copyright 2019-2024 - Licensed under MIT + */ + +const themeSwitcher = { + // Config + _scheme: "auto", + menuTarget: "details.dropdown", + buttonsTarget: "a[data-theme-switcher]", + buttonAttribute: "data-theme-switcher", + rootAttribute: "data-theme", + localStorageKey: "picoPreferredColorScheme", + + // Init + init() { + this.scheme = this.schemeFromLocalStorage; + this.initSwitchers(); + }, + + // Get color scheme from local storage + get schemeFromLocalStorage() { + return window.localStorage?.getItem(this.localStorageKey) ?? this._scheme; + }, + + // Preferred color scheme + get preferredColorScheme() { + return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"; + }, + + // Init switchers + initSwitchers() { + const buttons = document.querySelectorAll(this.buttonsTarget); + buttons.forEach((button) => { + button.addEventListener( + "click", + (event) => { + event.preventDefault(); + // Set scheme + this.scheme = button.getAttribute(this.buttonAttribute); + // Close dropdown + document.querySelector(this.menuTarget)?.removeAttribute("open"); + }, + false + ); + }); + }, + + // Set scheme + set scheme(scheme) { + if (scheme == "auto") { + this._scheme = this.preferredColorScheme; + } else if (scheme == "dark" || scheme == "light") { + this._scheme = scheme; + } + this.applyScheme(); + this.schemeToLocalStorage(); + }, + + // Get scheme + get scheme() { + return this._scheme; + }, + + // Apply scheme + applyScheme() { + document.querySelector("html")?.setAttribute(this.rootAttribute, this.scheme); + }, + + // Store scheme to local storage + schemeToLocalStorage() { + window.localStorage?.setItem(this.localStorageKey, this.scheme); + }, +}; + +// Init +themeSwitcher.init(); +""" + ) diff --git a/main.py b/main.py index 4eab471..726fe75 100644 --- a/main.py +++ b/main.py @@ -6,6 +6,7 @@ from fasthtml.common import * import grid3.network, grid3.minting +from lightdark import LightDarkScript, LightLink, DarkLink import minting_lite RECEIPTS_URL = "https://alpha.minting.tfchain.grid.tf/api/v1/" @@ -199,9 +200,18 @@ def render_main(select="node", id_input=None, result="", loading=False): )("Loading...") ] - return Body(onload=onload)( - Titled( - "Fetch Minting Receipts", + title = "Fetch Minting Receipts" + return Title(title), Body(onload=onload)( + # PicoCSS container, for centered view + Main(cls="container")( + Div(style="display: flex")( + H1(title), + Div(style="display:flex; flex-direction:column; margin-left:auto")( + Div(style="align-self:center")("Join the:"), + Div(LightLink("Light side"), " | ", DarkLink("Dark side")) + ), + ), + LightDarkScript(), Form( hx_get="/", hx_target="body",