From 300ae1b94f7d5e69f2e6cac9a835fa2a4089e5cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Sat, 29 Aug 2026 11:58:19 +0100 Subject: [PATCH] no Loading row either, since the header is a constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- web/RootLocationBlock.tsx | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/web/RootLocationBlock.tsx b/web/RootLocationBlock.tsx index 04e702d..74cd065 100644 --- a/web/RootLocationBlock.tsx +++ b/web/RootLocationBlock.tsx @@ -193,11 +193,19 @@ export const RootLocationBlock = () => { return shell(

Only the owner can change where the site lives.

); } - // 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. - if (!saved || !summary) { - return shell(

Loading…

); - } + /* + 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. + + 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;