no Loading row either, since the header is a constant

The last flicker was one line of text being replaced by another. The title and
the hint never depend on anything fetched, so they can paint immediately; only
the check on the right and the body have to wait.

So the loading state renders the header with nothing in it. The settled case —
nearly every load — goes from header to header-plus-check, and nothing on screen
moves.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-29 11:58:19 +01:00
co-authored by Claude Opus 5
parent e621bc761d
commit 300ae1b94f
+13 -5
View File
@@ -193,11 +193,19 @@ export const RootLocationBlock = () => {
return shell(<p className="text-xs text-muted-foreground">Only the owner can change where the site lives.</p>); return shell(<p className="text-xs text-muted-foreground">Only the owner can change where the site lives.</p>);
} }
// Both, not either. Rendering on the path alone puts the block on screen before it knows whether it /*
// is finished, which is the flicker this was all for. Both, not either — rendering on the path alone puts the block on screen before it knows whether it
if (!saved || !summary) { is finished, which is the flicker this was all for.
return shell(<p className="text-xs text-muted-foreground">Loading…</p>);
} And it renders the HEADER, with nothing in it. Not a "Loading…" row: that is a line of text which
then gets replaced by a different line of text, which is a flicker in its own right and was the one
left over after the last fix. The title and the hint are constants and can paint immediately; what
waits for data is the check on the right and whatever body turns out to be needed.
So the settled case — which is nearly every load — goes from header to header-plus-check, and
nothing moves at all.
*/
if (!saved || !summary) return shell(null);
const dirty = value.trim() !== saved.rootPath; const dirty = value.trim() !== saved.rootPath;