fix(page-history): gate nav-panel empty state on !isLoading to kill load-flash (#568)

HistoryNavPanel only received isError, not isLoading, so during the initial
history query (data undefined -> empty groups, isError false) it flashed the
false 'No page history saved yet.' text until rows arrived. Thread isLoading
in and gate the empty branch on !isLoading, mirroring the right pane. Add a
loading-state test asserting the empty text is not shown while isLoading.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-13 04:26:22 +03:00
parent 7743278a92
commit 8124d5c2ba
3 changed files with 36 additions and 2 deletions
@@ -214,6 +214,7 @@ export default function HistoryModalDesktop({ pageId, onClose }: Props) {
hasNextPage={!!hasNextPage}
isFetchingNextPage={isFetchingNextPage}
isError={isError}
isLoading={isLoading}
counts={counts}
selectedDayISO={selectedRow?.dayISO ?? null}
tz={tz}
@@ -49,6 +49,7 @@ function Harness({
hasNextPage={false}
isFetchingNextPage={false}
isError={false}
isLoading={false}
counts={counts}
selectedDayISO={todayISO}
tz={TZ}
@@ -109,6 +110,7 @@ describe("HistoryNavPanel (#568 left nav)", () => {
hasNextPage={false}
isFetchingNextPage={false}
isError
isLoading={false}
counts={new Map()}
selectedDayISO={null}
tz={TZ}
@@ -132,6 +134,7 @@ describe("HistoryNavPanel (#568 left nav)", () => {
hasNextPage={false}
isFetchingNextPage={false}
isError={false}
isLoading={false}
counts={new Map()}
selectedDayISO={null}
tz={TZ}
@@ -142,4 +145,30 @@ describe("HistoryNavPanel (#568 left nav)", () => {
);
expect(screen.getByText("No page history saved yet.")).toBeDefined();
});
it("does NOT flash the empty text while the initial query is loading", () => {
// F1-residual: during the first fetch data is empty but isLoading is true —
// the empty state must stay hidden until loading settles (mirrors the right
// pane). Reverting the `!isLoading` gate makes this fail.
render(
<MantineProvider>
<HistoryNavPanel
fullItems={[]}
activeId=""
onSelect={vi.fn()}
fetchNextPage={vi.fn() as any}
hasNextPage={false}
isFetchingNextPage={false}
isError={false}
isLoading={true}
counts={new Map()}
selectedDayISO={null}
tz={TZ}
onlyVersions={false}
setOnlyVersions={vi.fn()}
/>
</MantineProvider>,
);
expect(screen.queryByText("No page history saved yet.")).toBeNull();
});
});
@@ -30,6 +30,7 @@ interface Props {
hasNextPage: boolean;
isFetchingNextPage: boolean;
isError: boolean;
isLoading: boolean;
counts: Map<string, number>;
selectedDayISO: string | null;
tz: string;
@@ -53,6 +54,7 @@ export default function HistoryNavPanel({
hasNextPage,
isFetchingNextPage,
isError,
isLoading,
counts,
selectedDayISO,
tz,
@@ -159,14 +161,16 @@ export default function HistoryNavPanel({
<ScrollArea style={{ flex: 1 }} viewportRef={viewportRef} scrollbarSize={5}>
{/* F1 — explicit error/empty states instead of a blank panel. The
heatmap fails open independently; the list keeps its own states. */}
heatmap fails open independently; the list keeps its own states.
The empty state is gated on !isLoading so it doesn't flash the
"no history" text during the initial query, mirroring the right pane. */}
{isError ? (
<Center py="md" px="sm">
<Text size="sm" c="dimmed" ta="center">
{t("Error loading page history.")}
</Text>
</Center>
) : groups.length === 0 ? (
) : !isLoading && groups.length === 0 ? (
<Center py="md" px="sm">
<Text size="sm" c="dimmed" ta="center">
{onlyVersions