From 7e1ccad5f447abf0fdd3579f4981cce5d362a36c Mon Sep 17 00:00:00 2001 From: dtoro Date: Tue, 28 Jul 2026 08:44:52 +0200 Subject: [PATCH] fix(web): replace generic spinners with content-shaped loading skeletons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The six loading states across the Knowledge wiki (initial app load, the reader's note/history fetches, and the four Cleanup tabs) all showed a centered spinner with no relation to what was about to render — costing a full reflow the instant real content landed. Replaces each with a skeleton shaped like its actual content (tree rows, reader header + prose, revision list + diff, cluster cards, table rows, flat lists) using the existing shadcn Skeleton primitive already used elsewhere. Verified each of the six by temporarily injecting a delay into fetchWithAuth and screenshotting the transient state. Co-Authored-By: Claude Sonnet 5 --- .../components/knowledge/WikiCleanup.svelte | 68 +++++++++++++++++-- .../components/knowledge/WikiReader.svelte | 46 ++++++++++++- web/src/pages/Knowledge.svelte | 49 ++++++++++++- 3 files changed, 151 insertions(+), 12 deletions(-) diff --git a/web/src/lib/components/knowledge/WikiCleanup.svelte b/web/src/lib/components/knowledge/WikiCleanup.svelte index 90287f9..04909e5 100644 --- a/web/src/lib/components/knowledge/WikiCleanup.svelte +++ b/web/src/lib/components/knowledge/WikiCleanup.svelte @@ -28,7 +28,7 @@ import { Button } from '$lib/components/ui/button' import { Input } from '$lib/components/ui/input' import { Badge } from '$lib/components/ui/badge' - import Spinner from '$lib/components/Spinner.svelte' + import { Skeleton } from '$lib/components/ui/skeleton' import { toast } from 'svelte-sonner' import { kindMeta } from './kinds' import { relativeTime } from '$lib/utils' @@ -89,7 +89,7 @@ mergeSources = sources } catch (e) { duplicatesError = errMsg(e) - clusters = [] // stop the spinner — the error message above explains the empty state + clusters = [] // clear the loading skeleton — the error message above explains the empty state } } @@ -289,7 +289,23 @@

{/if} {#if clusters === null} -
+
+ {#each Array(2) as _, ci (ci)} +
+
+ + +
+
+ {#each Array(ci === 0 ? 3 : 2) as _, ri (ri)} + + {/each} +
+
+ {/each} +
{:else if clusters.length === 0}

No likely duplicates found.

{:else} @@ -412,7 +428,31 @@

{/if} {#if tags === null} -
+ + + + + + + + + + + {#each Array(10) as _, i (i)} + + + + + + + + {/each} + +
TagUsesVariants
+ +
{:else} {@const maxUses = Math.max(1, ...tags.map((t) => t.uses))} @@ -509,7 +549,15 @@

{/if} {#if orphans === null} -
+
+ {#each Array(7) as _, i (i)} +
+ + + +
+ {/each} +
{:else if orphans.length === 0}

Nothing orphaned.

{:else} @@ -541,7 +589,15 @@

{/if} {#if trash === null} -
+
+ {#each Array(4) as _, i (i)} +
+ + + +
+ {/each} +
{:else if trash.length === 0}

Trash is empty.

{:else} diff --git a/web/src/lib/components/knowledge/WikiReader.svelte b/web/src/lib/components/knowledge/WikiReader.svelte index 0130046..c395f96 100644 --- a/web/src/lib/components/knowledge/WikiReader.svelte +++ b/web/src/lib/components/knowledge/WikiReader.svelte @@ -27,7 +27,7 @@ import { Button } from '$lib/components/ui/button' import { Input } from '$lib/components/ui/input' import { Textarea } from '$lib/components/ui/textarea' - import Spinner from '$lib/components/Spinner.svelte' + import { Skeleton } from '$lib/components/ui/skeleton' import PencilIcon from '@lucide/svelte/icons/pencil' import TrashIcon from '@lucide/svelte/icons/trash-2' import HistoryIcon from '@lucide/svelte/icons/history' @@ -224,7 +224,33 @@ {#if !item} {:else if loading} -
+ +
+
+
+ + +
+
+ + + +
+
+ +
+
+ + +
+
+ {#each Array(6) as _, i (i)} + + {/each} +
{:else if !content}
Couldn't load this note. @@ -374,7 +400,21 @@ {#if revisionsLoading} -
+
+
+ {#each Array(4) as _, i (i)} +
+ + +
+ {/each} +
+
+ {#each Array(8) as _, i (i)} + + {/each} +
+
{:else if !revisions || revisions.length === 0}

No prior revisions — this is the first version. diff --git a/web/src/pages/Knowledge.svelte b/web/src/pages/Knowledge.svelte index 53205d7..2ec1199 100644 --- a/web/src/pages/Knowledge.svelte +++ b/web/src/pages/Knowledge.svelte @@ -20,6 +20,7 @@ import WikiQuickOpen from '$lib/components/knowledge/WikiQuickOpen.svelte' import * as Dialog from '$lib/components/ui/dialog' import { Button } from '$lib/components/ui/button' + import { Skeleton } from '$lib/components/ui/skeleton' import WrenchIcon from '@lucide/svelte/icons/wrench' import BookOpenIcon from '@lucide/svelte/icons/book-open' @@ -149,9 +150,51 @@

{#if itemsLoading} -
- Loading… -
+ + + +
+ + +
+ {#each Array(4) as _, gi (gi)} +
+ +
+ {#each Array(3) as _, ri (ri)} + + {/each} +
+
+ {/each} +
+
+
+ +
+ + +
+ {#each Array(4) as _, i (i)} +
+ + +
+ {/each} +
+ +
+ {#each Array(5) as _, i (i)} + + {/each} +
+
+
+
{:else if loadError}

{loadError}