Add landing page for kjol, documentation

This commit is contained in:
2026-07-13 16:51:21 -04:00
parent 5230bd6702
commit fec8ef4a3e
54 changed files with 3529 additions and 547 deletions

View File

@@ -67,8 +67,63 @@ func CSSVarPx(name string) float64 {
return parseCSSLength(raw, style.Get("fontSize").String())
}
// ---- theme ----
// PrefersDark reports whether the OS asks for a dark colour scheme.
func PrefersDark() bool {
mq := window.Call("matchMedia", "(prefers-color-scheme: dark)")
return mq.Truthy() && mq.Get("matches").Bool()
}
// OnMediaChange watches a media query. The theme controller uses it to follow the OS
// while the user has not overridden it — a preference changed in the system settings
// should reach an open tab, not wait for a reload.
func OnMediaChange(query string, fn func(matches bool)) Unsub {
mq := window.Call("matchMedia", query)
if !mq.Truthy() {
return func() {}
}
cb := js.FuncOf(func(_ js.Value, args []js.Value) any {
matches := false
if len(args) > 0 {
matches = args[0].Get("matches").Bool()
}
fn(matches)
return nil
})
mq.Call("addEventListener", "change", cb)
return func() {
mq.Call("removeEventListener", "change", cb)
cb.Release()
}
}
// SetRootClass adds or removes a class on <html>.
//
// The THEME lives there rather than on the app's root element because the page's own
// background — the thing behind everything, painted before the app mounts — is styled
// from <html>. A dark class on #app leaves a white margin around a dark page.
func SetRootClass(class string, on bool) {
list := document.Get("documentElement").Get("classList")
if on {
list.Call("add", class)
return
}
list.Call("remove", class)
}
// ---- frame timing + the post-render hook ----
// Now is performance.now(): milliseconds since the page began navigating, with
// sub-millisecond resolution.
//
// It is measured from the same origin the browser uses for its own timings, so a
// reading taken when the first render commits IS the time it took this app to become
// interactive — not an interval the app started and stopped itself.
func Now() float64 {
return window.Get("performance").Call("now").Float()
}
func RAF(fn func()) int {
var cb js.Func
cb = js.FuncOf(func(js.Value, []js.Value) any {