refactor(search): remove smart mode from SearchFilterBar
Removes SmartModeToggle component import and all smart-mode conditional logic from SearchFilterBar, including mode-specific input handling, max-length constraints, and CSS class toggling. Removes associated smart-mode tests that verified chip lifecycle callbacks (onModeToggle, onSmartSearch). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,6 @@ import PersonTypeahead from '$lib/person/PersonTypeahead.svelte';
|
|||||||
import TagInput from '$lib/tag/TagInput.svelte';
|
import TagInput from '$lib/tag/TagInput.svelte';
|
||||||
import DateInput from '$lib/shared/primitives/DateInput.svelte';
|
import DateInput from '$lib/shared/primitives/DateInput.svelte';
|
||||||
import SortDropdown from '$lib/shared/primitives/SortDropdown.svelte';
|
import SortDropdown from '$lib/shared/primitives/SortDropdown.svelte';
|
||||||
import SmartModeToggle from './search/SmartModeToggle.svelte';
|
|
||||||
import { slide } from 'svelte/transition';
|
import { slide } from 'svelte/transition';
|
||||||
import { m } from '$lib/paraglide/messages.js';
|
import { m } from '$lib/paraglide/messages.js';
|
||||||
|
|
||||||
@@ -21,15 +20,12 @@ let {
|
|||||||
sort = $bindable('DATE'),
|
sort = $bindable('DATE'),
|
||||||
dir = $bindable('desc'),
|
dir = $bindable('desc'),
|
||||||
showAdvanced = $bindable(false),
|
showAdvanced = $bindable(false),
|
||||||
smartMode = $bindable(false),
|
|
||||||
initialSenderName = '',
|
initialSenderName = '',
|
||||||
initialReceiverName = '',
|
initialReceiverName = '',
|
||||||
navKey = 0,
|
navKey = 0,
|
||||||
isLoading = false,
|
isLoading = false,
|
||||||
onSearch,
|
onSearch,
|
||||||
onSearchImmediate,
|
onSearchImmediate,
|
||||||
onSmartSearch,
|
|
||||||
onModeToggle,
|
|
||||||
onfocus,
|
onfocus,
|
||||||
onblur
|
onblur
|
||||||
}: {
|
}: {
|
||||||
@@ -46,28 +42,16 @@ let {
|
|||||||
sort?: string;
|
sort?: string;
|
||||||
dir?: string;
|
dir?: string;
|
||||||
showAdvanced?: boolean;
|
showAdvanced?: boolean;
|
||||||
smartMode?: boolean;
|
|
||||||
initialSenderName?: string;
|
initialSenderName?: string;
|
||||||
initialReceiverName?: string;
|
initialReceiverName?: string;
|
||||||
navKey?: number;
|
navKey?: number;
|
||||||
isLoading?: boolean;
|
isLoading?: boolean;
|
||||||
onSearch: () => void;
|
onSearch: () => void;
|
||||||
onSearchImmediate?: () => void;
|
onSearchImmediate?: () => void;
|
||||||
onSmartSearch?: () => void;
|
|
||||||
onModeToggle?: () => void;
|
|
||||||
onfocus?: () => void;
|
onfocus?: () => void;
|
||||||
onblur?: () => void;
|
onblur?: () => void;
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
// In smart mode the keyword search must not fire on every keystroke — the NL
|
|
||||||
// query is submitted only on Enter (or an explicit button click).
|
|
||||||
function onSearchKeydown(event: KeyboardEvent) {
|
|
||||||
if (smartMode && event.key === 'Enter') {
|
|
||||||
event.preventDefault();
|
|
||||||
onSmartSearch?.();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Plain (non-reactive) flag — not $state, so no reactive assignment inside $effect
|
// Plain (non-reactive) flag — not $state, so no reactive assignment inside $effect
|
||||||
let sortDirMounted = false;
|
let sortDirMounted = false;
|
||||||
|
|
||||||
@@ -92,19 +76,13 @@ $effect(() => {
|
|||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
bind:value={q}
|
bind:value={q}
|
||||||
oninput={smartMode ? undefined : onSearch}
|
oninput={onSearch}
|
||||||
onkeydown={onSearchKeydown}
|
|
||||||
onfocus={onfocus}
|
onfocus={onfocus}
|
||||||
onblur={onblur}
|
onblur={onblur}
|
||||||
maxlength={smartMode ? 500 : undefined}
|
|
||||||
aria-label={m.docs_search_placeholder()}
|
aria-label={m.docs_search_placeholder()}
|
||||||
placeholder={m.docs_search_placeholder()}
|
placeholder={m.docs_search_placeholder()}
|
||||||
class="block w-full border-line py-2.5 pl-10 placeholder-ink-3 shadow-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring {smartMode
|
class="block w-full border-line py-2.5 pr-20 pl-10 placeholder-ink-3 shadow-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring"
|
||||||
? 'pr-28'
|
|
||||||
: 'pr-20'}"
|
|
||||||
/>
|
/>
|
||||||
<!-- Decorative search icon / loading spinner — left slot keeps the right
|
|
||||||
slot free for the always-visible smart-mode toggle pill. -->
|
|
||||||
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
|
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
|
||||||
{#if isLoading}
|
{#if isLoading}
|
||||||
<svg
|
<svg
|
||||||
@@ -132,7 +110,6 @@ $effect(() => {
|
|||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<SmartModeToggle bind:smartMode={smartMode} onToggle={onModeToggle} />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Sort Dropdown -->
|
<!-- Sort Dropdown -->
|
||||||
|
|||||||
@@ -195,39 +195,3 @@ describe('SearchFilterBar – tagQ live filter', () => {
|
|||||||
vi.unstubAllGlobals();
|
vi.unstubAllGlobals();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('SearchFilterBar – smart-mode chip lifecycle hooks', () => {
|
|
||||||
// The interpretation chips live in the result area (parent page). SearchFilterBar
|
|
||||||
// drives chip-clearing through callbacks: onModeToggle (mode switch) and
|
|
||||||
// onSmartSearch (new query). These tests pin that contract.
|
|
||||||
it('invokes onModeToggle when toggling back to keyword mode (parent clears chips)', async () => {
|
|
||||||
const onModeToggle = vi.fn();
|
|
||||||
render(SearchFilterBar, {
|
|
||||||
...defaultProps,
|
|
||||||
sort: 'DATE',
|
|
||||||
dir: 'desc',
|
|
||||||
smartMode: true,
|
|
||||||
onModeToggle
|
|
||||||
});
|
|
||||||
await page.getByRole('button', { name: /Smart/ }).click();
|
|
||||||
expect(onModeToggle).toHaveBeenCalledOnce();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('invokes onSmartSearch when a new query is submitted in smart mode (parent resets chips)', async () => {
|
|
||||||
const onSmartSearch = vi.fn();
|
|
||||||
render(SearchFilterBar, {
|
|
||||||
...defaultProps,
|
|
||||||
sort: 'DATE',
|
|
||||||
dir: 'desc',
|
|
||||||
smartMode: true,
|
|
||||||
onSmartSearch
|
|
||||||
});
|
|
||||||
const input = page.getByPlaceholder('Titel, Personen, Tags durchsuchen…');
|
|
||||||
await input.fill('Walter im Krieg');
|
|
||||||
await input.click();
|
|
||||||
(document.activeElement as HTMLElement).dispatchEvent(
|
|
||||||
new KeyboardEvent('keydown', { key: 'Enter', bubbles: true })
|
|
||||||
);
|
|
||||||
await vi.waitFor(() => expect(onSmartSearch).toHaveBeenCalled());
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
Reference in New Issue
Block a user