Spec measurements (7px/8px/9px text) were spec-document zoom artifacts — not viable at real browser scale. Updated to readable compact sizes: - Row 1 compact label: text-xs (12px) uppercase instead of 7px - Row 1 input: h-9 text-sm (36px/14px) instead of 30px/9px - Row 1 swap button: h-9 w-9 to align with taller inputs - Row 2 date inputs: h-8 text-xs (32px/12px) instead of 22px/8px - Row 2 label/count/sort: text-xs instead of 7px/8px Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
111 lines
2.8 KiB
Svelte
111 lines
2.8 KiB
Svelte
<script lang="ts">
|
|
import PersonTypeahead from '$lib/components/PersonTypeahead.svelte';
|
|
import CorrespondentSuggestionsDropdown from './CorrespondentSuggestionsDropdown.svelte';
|
|
|
|
interface Props {
|
|
senderId?: string;
|
|
receiverId?: string;
|
|
initialSenderName?: string;
|
|
initialReceiverName?: string;
|
|
onapplyFilters: () => void;
|
|
onswapPersons: () => void;
|
|
}
|
|
|
|
let {
|
|
senderId = $bindable(''),
|
|
receiverId = $bindable(''),
|
|
initialSenderName = '',
|
|
initialReceiverName = '',
|
|
onapplyFilters,
|
|
onswapPersons
|
|
}: Props = $props();
|
|
|
|
let swapVisible = $derived(!!(senderId && receiverId));
|
|
|
|
let showSuggestions = $state(false);
|
|
|
|
function handleCorrespondentFocused() {
|
|
if (senderId) showSuggestions = true;
|
|
}
|
|
|
|
function handleSuggestionSelect(id: string) {
|
|
receiverId = id;
|
|
showSuggestions = false;
|
|
onapplyFilters();
|
|
}
|
|
</script>
|
|
|
|
<div class="flex items-end gap-[9px] border-b border-line bg-surface px-4 py-[9px] sm:px-[18px]">
|
|
<!-- Person A -->
|
|
<div class="min-w-0 flex-1">
|
|
<PersonTypeahead
|
|
name="senderId"
|
|
label="Person"
|
|
bind:value={senderId}
|
|
initialName={initialSenderName}
|
|
compact={true}
|
|
restrictToCorrespondentsOf={receiverId || undefined}
|
|
onchange={() => onapplyFilters()}
|
|
/>
|
|
</div>
|
|
|
|
<!-- Swap button -->
|
|
<button
|
|
data-testid="conv-swap-btn"
|
|
type="button"
|
|
aria-label="Personen tauschen"
|
|
onclick={onswapPersons}
|
|
class="flex h-9 w-9 shrink-0 items-center justify-center rounded border border-line bg-surface text-ink-3 transition-colors hover:border-primary hover:text-primary"
|
|
class:opacity-0={!swapVisible}
|
|
class:pointer-events-none={!swapVisible}
|
|
tabindex={swapVisible ? 0 : -1}
|
|
>
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="14"
|
|
height="14"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
aria-hidden="true"
|
|
>
|
|
<path d="M7 16V4m0 0L3 8m4-4l4 4" />
|
|
<path d="M17 8v12m0 0l4-4m-4 4l-4-4" />
|
|
</svg>
|
|
</button>
|
|
|
|
<!-- Korrespondent field -->
|
|
<div
|
|
class="relative min-w-0 flex-1"
|
|
class:[&_input]:border-dashed={!receiverId}
|
|
class:[&_input]:border-solid={!!receiverId}
|
|
class:[&_input]:bg-canvas={!receiverId}
|
|
>
|
|
<PersonTypeahead
|
|
name="receiverId"
|
|
label={receiverId ? 'Korrespondent' : 'Korrespondent — optional'}
|
|
bind:value={receiverId}
|
|
initialName={initialReceiverName}
|
|
compact={true}
|
|
placeholder="Alle Korrespondenten"
|
|
restrictToCorrespondentsOf={senderId || undefined}
|
|
onchange={() => {
|
|
showSuggestions = false;
|
|
onapplyFilters();
|
|
}}
|
|
onfocused={handleCorrespondentFocused}
|
|
/>
|
|
{#if showSuggestions && senderId && !receiverId}
|
|
<CorrespondentSuggestionsDropdown
|
|
senderId={senderId}
|
|
senderName=""
|
|
onselect={handleSuggestionSelect}
|
|
onclose={() => (showSuggestions = false)}
|
|
/>
|
|
{/if}
|
|
</div>
|
|
</div>
|