fix(person-mention): show loading state during debounce + fetch

Leonie #5507 concern 7: on slow networks the popup sat empty for up to
1.5s while the user wondered if anything was happening. Add a loading
flag that flips on as soon as scheduleSearch is asked to query and
back off in the fetch's finally branch. Reuses the existing
comp_typeahead_loading message ("Suche…") so no new i18n keys.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-29 01:14:37 +02:00
parent 780c682136
commit 86ad5ca9b3

View File

@@ -37,6 +37,7 @@ let query: string | null = $state(null);
let results: Person[] = $state([]);
let highlightedIndex = $state(0);
let mentionStart = $state(0);
let loading = $state(false);
let textarea: HTMLTextAreaElement | null = null;
let debounceTimer: ReturnType<typeof setTimeout> | undefined;
@@ -90,8 +91,10 @@ function scheduleSearch(q: string) {
// Empty query: keep popup open with last results so the user can browse,
// but don't fire a backend call until they actually type something.
results = [];
loading = false;
return;
}
loading = true;
debounceTimer = setTimeout(async () => {
try {
// SECURITY: relies on the SvelteKit Vite proxy injecting the auth_token
@@ -108,6 +111,8 @@ function scheduleSearch(q: string) {
}
} catch {
results = [];
} finally {
loading = false;
}
}, 200);
}
@@ -140,6 +145,7 @@ function closePopup() {
query = null;
results = [];
highlightedIndex = 0;
loading = false;
clearTimeout(debounceTimer);
}
@@ -208,7 +214,9 @@ const popupOpen = $derived(query !== null);
role="listbox"
aria-label={m.person_mention_btn_label()}
>
{#if results.length === 0}
{#if loading}
<p class="px-3 py-2 font-sans text-sm text-ink-3">{m.comp_typeahead_loading()}</p>
{:else if results.length === 0}
<p class="px-3 py-2 font-sans text-sm text-ink-3">{m.person_mention_popup_empty()}</p>
{:else}
{#each results as person, i (person.id)}