Files
zeekay b54fe45c68 Follow the device's light or dark scheme, and draw /zen's generations as rules
A reader who had never chosen a theme got dark whatever the device said: the
head's boot script was seeded with `dark`. The install's default is now
`system` (lib/appearance.ts), painted before the first frame, and the client
applies it once mounted, which is what installs the listener that follows the
device when it changes.

/zen's generations, the timeline marks and the Train/Attest/Evaluate/Release
underlines set `borderStyle` with one side's width, so the other three sides
drew at the browser's medium width: every generation was a 3px box with its
text against the edge. Each now sets `borderWidth={0}` before its side.

Gate e2e/gates/scheme.spec.ts: a first visit under a light and a dark device
paints that scheme and follows a change, and /zen's generations read
1px 0 0 0. The look gate still passes.

Claude-Session: https://claude.ai/code/session_01SCPMGSQsLNF2YtHFL4bwyp
2026-10-08 11:52:12 -07:00

50 lines
1.8 KiB
TypeScript

'use client'
/**
* The gui runtime, mounted once.
*
* gui's atomic CSS does NOT come from here. It is generated from `lib/gui.ts`
* into `app/gui.css` by `prebuild` (scripts/gen-gui-css.mjs) and imported by the
* root layout, so Next fingerprints it and the browser caches it once.
*
* This used to hand `config.getCSS()` to `useServerInsertedHTML`, which Next runs
* on EVERY streaming flush — and since getCSS() returns the whole accumulated
* sheet each time, the homepage shipped thirteen byte-identical copies: 591,305
* of its 638,443 bytes, uncacheable, re-sent on every navigation. `href` +
* `precedence` do not fix it either, because useServerInsertedHTML injects into
* the stream outside the React tree, where hoisting never reconciles.
*
* `disableInjectCSS` is what keeps that from coming back: with the sheet supplied
* statically, a second copy from the runtime would be pure duplication.
*/
import * as React from 'react'
import { GuiProvider as Gui } from '@hanzo/gui'
import { apply, current, useScheme } from '@hanzo/appearance'
import config from '@/lib/gui'
import { INSTALL } from '@/lib/appearance'
export function GuiProvider({ children }: { children: React.ReactNode }) {
// The theme the document shows — painted by @hanzo/appearance as `light` /
// `t_light` (or `dark` / `t_dark`) before the first frame and on every change.
const scheme = useScheme()
// The boot script painted the reader's choice, else the install's default,
// but only `apply()` keeps a `system` theme following the device: it installs
// the one listener that repaints on a change of prefers-color-scheme.
React.useEffect(() => {
apply(current({ install: INSTALL }).pref)
}, [])
return (
<Gui
config={config}
defaultTheme={scheme}
disableRootThemeClass
disableInjectCSS
>
{children}
</Gui>
)
}