feat(search): show spinner in search input while navigation is in-flight
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { navigating } from '$app/state';
|
||||
import { untrack } from 'svelte';
|
||||
import { SvelteURLSearchParams } from 'svelte/reactivity';
|
||||
import SearchFilterBar from './SearchFilterBar.svelte';
|
||||
@@ -102,6 +103,7 @@ const showRightColumn = $derived(data.canWrite || (data.incompleteDocs?.length ?
|
||||
bind:tagQ={tagQ}
|
||||
initialSenderName={data.initialValues?.senderName}
|
||||
initialReceiverName={data.initialValues?.receiverName}
|
||||
isLoading={navigating.to !== null}
|
||||
onSearch={handleTextSearch}
|
||||
onfocus={() => (qFocused = true)}
|
||||
onblur={() => (qFocused = false)}
|
||||
|
||||
@@ -18,6 +18,7 @@ let {
|
||||
showAdvanced = $bindable(false),
|
||||
initialSenderName = '',
|
||||
initialReceiverName = '',
|
||||
isLoading = false,
|
||||
onSearch,
|
||||
onfocus,
|
||||
onblur
|
||||
@@ -34,6 +35,7 @@ let {
|
||||
showAdvanced?: boolean;
|
||||
initialSenderName?: string;
|
||||
initialReceiverName?: string;
|
||||
isLoading?: boolean;
|
||||
onSearch: () => void;
|
||||
onfocus?: () => void;
|
||||
onblur?: () => void;
|
||||
@@ -70,12 +72,31 @@ $effect(() => {
|
||||
class="block w-full border-line py-2.5 pr-10 pl-3 placeholder-ink-3 shadow-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring"
|
||||
/>
|
||||
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3">
|
||||
<img
|
||||
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Mag-Glass-MD.svg"
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
class="h-4 w-4 opacity-40"
|
||||
/>
|
||||
{#if isLoading}
|
||||
<svg
|
||||
role="status"
|
||||
aria-label="Suche läuft…"
|
||||
class="h-4 w-4 animate-spin text-ink-3"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"
|
||||
></circle>
|
||||
<path
|
||||
class="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
|
||||
></path>
|
||||
</svg>
|
||||
{:else}
|
||||
<img
|
||||
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Mag-Glass-MD.svg"
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
class="h-4 w-4 opacity-40"
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -27,6 +27,20 @@ describe('SearchFilterBar – sort controls', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('SearchFilterBar – loading spinner', () => {
|
||||
it('shows search icon when isLoading is false', async () => {
|
||||
render(SearchFilterBar, { ...defaultProps, sort: 'DATE', dir: 'desc', isLoading: false });
|
||||
const spinner = page.getByRole('status');
|
||||
await expect.element(spinner).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows spinner and hides search icon when isLoading is true', async () => {
|
||||
render(SearchFilterBar, { ...defaultProps, sort: 'DATE', dir: 'desc', isLoading: true });
|
||||
const spinner = page.getByRole('status');
|
||||
await expect.element(spinner).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('SearchFilterBar – tagQ live filter', () => {
|
||||
it('calls onSearch when tag text changes in TagInput', async () => {
|
||||
vi.stubGlobal(
|
||||
|
||||
@@ -240,6 +240,16 @@ describe('Home page – error state', () => {
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Loading spinner ──────────────────────────────────────────────────────────
|
||||
|
||||
describe('Home page – loading spinner', () => {
|
||||
it('does not show spinner by default', async () => {
|
||||
render(Page, { data: emptyData });
|
||||
const spinner = page.getByRole('status');
|
||||
await expect.element(spinner).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Sort controls ────────────────────────────────────────────────────────────
|
||||
|
||||
describe('Home page – sort controls', () => {
|
||||
|
||||
Reference in New Issue
Block a user