fix(frontend): the content is padded by the filled header before paint, not when the observer catches up

The header's pills now arrive by portal after the shell has mounted, so the shell's one synchronous
measurement saw an empty header, and the ResizeObserver brought `--hdr-h` up a frame or more later:
meanwhile the content sat under the pills (the feed toolbar jumped 55px on a tablet; e2e caught it).
The measurement re-runs before paint whenever what fills the header changes.
This commit is contained in:
2026-10-23 03:24:23 +02:00
parent 6a0c1d377f
commit e83c5e2d97
3 changed files with 60 additions and 11 deletions
+5 -2
View File
@@ -1,14 +1,17 @@
import { createContext } from "react";
// The floating header's slot (see PageHeader in PageShell): the node a page portals its header
// controls into, whether a page has claimed it, and how a page claims it. Null with no shell, or in a
// shell without a header (the channel page), so a page renders its header nowhere there. Its own
// controls into, whether a page has claimed it, and how a page claims it. The value is null with no
// shell and the target null in a shell without a header (the channel page): a page renders its header
// nowhere there. Its own
// module so PageShell exports only components (Fast Refresh).
export type PageHeaderSlotValue = {
target: HTMLElement | null;
claimed: boolean;
/** Claim the header for this page's controls; the returned function releases it. */
claim: () => () => void;
/** The default (PageHeaderDefault) reports whether it is in the header, so PageShell re-measures. */
showDefault: (shown: boolean) => void;
};
export const PageHeaderSlot = createContext<PageHeaderSlotValue | null>(null);