fix(stammbaum): seed gutter media-query state synchronously (#689)
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 2m32s
CI / OCR Service Tests (pull_request) Successful in 23s
CI / Backend Unit Tests (pull_request) Successful in 3m39s
CI / fail2ban Regex (pull_request) Failing after 45s
CI / Semgrep Security Scan (pull_request) Successful in 24s
CI / Compose Bucket Idempotency (pull_request) Successful in 1m4s
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 2m32s
CI / OCR Service Tests (pull_request) Successful in 23s
CI / Backend Unit Tests (pull_request) Successful in 3m39s
CI / fail2ban Regex (pull_request) Failing after 45s
CI / Semgrep Security Scan (pull_request) Successful in 24s
CI / Compose Bucket Idempotency (pull_request) Successful in 1m4s
CI flagged two browser tests:
- "renders a G{n} label per occupied generation row …"
- "wraps the visible G3 text inside an aria-labelled group …"
Both queried g[role="text"] and got an empty array. Root cause:
isMdOrUp was initialised to false and only flipped to true inside a
$effect — but $effect runs after the first render, so the test's
post-render DOM scan saw the pre-effect (gutter-absent) state.
Seed the rune synchronously from window.matchMedia(...).matches when
window is available; SSR still picks the false branch and hydrates
without a layout flash. The effect now only attaches the change
listener for subsequent resizes.
Refs #689
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -30,11 +30,17 @@ const layout = $derived.by<Layout>(() => buildLayout(nodes, edges));
|
||||
// too costly on a 320 px screen).
|
||||
const GUTTER_WIDTH_DESKTOP = 100;
|
||||
const GUTTER_MEDIA_QUERY = '(min-width: 768px)';
|
||||
let isMdOrUp = $state(false);
|
||||
// Seed synchronously so the first paint already has the right gutter state —
|
||||
// otherwise the test (and a brief flash on real CSR mount) would see the
|
||||
// pre-effect false. SSR has no window; the gutter stays hidden until hydrate.
|
||||
let isMdOrUp = $state(
|
||||
typeof window !== 'undefined' && typeof window.matchMedia === 'function'
|
||||
? window.matchMedia(GUTTER_MEDIA_QUERY).matches
|
||||
: false
|
||||
);
|
||||
$effect(() => {
|
||||
if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return;
|
||||
const mq = window.matchMedia(GUTTER_MEDIA_QUERY);
|
||||
isMdOrUp = mq.matches;
|
||||
const handler = (e: MediaQueryListEvent) => (isMdOrUp = e.matches);
|
||||
mq.addEventListener('change', handler);
|
||||
return () => mq.removeEventListener('change', handler);
|
||||
|
||||
Reference in New Issue
Block a user