From 0387e9f428df468ad043d114fad892c18efebde6 Mon Sep 17 00:00:00 2001 From: Marcel Date: Mon, 30 Mar 2026 13:57:00 +0200 Subject: [PATCH] fix(korrespondenz): address 10 visual and functional regressions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Strip full-bleed: remove max-w container, put strips at page level - Remove page heading/subtitle above strip (not in spec) - Swap button always visible (drop opacity-0, keep pointer-events-none) - Korrespondent placeholder "Alle Korrespondenten" + label "— optional" - Add placeholder prop to PersonTypeahead; add onfocused callback prop - "Person suchen" button now focuses #senderId-search instead of no-op navigate - Wire CorrespondentSuggestionsDropdown on correspondent field focus - Hint bar: bold name via , year-only dates (no ISO strings) - Asymmetry bar: use first name only to prevent label overflow Co-Authored-By: Claude Sonnet 4.6 --- .../src/lib/components/PersonTypeahead.svelte | 9 ++- .../src/routes/korrespondenz/+page.svelte | 72 +++++++++---------- .../korrespondenz/ConversationTimeline.svelte | 7 +- .../CorrespondenzPersonBar.svelte | 36 +++++++--- .../korrespondenz/SinglePersonHintBar.svelte | 23 +++--- 5 files changed, 83 insertions(+), 64 deletions(-) diff --git a/frontend/src/lib/components/PersonTypeahead.svelte b/frontend/src/lib/components/PersonTypeahead.svelte index 5196108a..dfd4051f 100644 --- a/frontend/src/lib/components/PersonTypeahead.svelte +++ b/frontend/src/lib/components/PersonTypeahead.svelte @@ -10,8 +10,10 @@ interface Props { value?: string; initialName?: string; suggestedName?: string; + placeholder?: string; restrictToCorrespondentsOf?: string; onchange?: (value: string) => void; + onfocused?: () => void; } let { @@ -20,8 +22,10 @@ let { value = $bindable(''), initialName = '', suggestedName = '', + placeholder, restrictToCorrespondentsOf, - onchange + onchange, + onfocused }: Props = $props(); let searchTerm = $state(initialName); @@ -79,6 +83,7 @@ function handleInput() { } function handleFocus() { + onfocused?.(); showDropdown = true; if (restrictToCorrespondentsOf) { const personId = untrack(() => restrictToCorrespondentsOf)!; @@ -131,7 +136,7 @@ function clickOutside(node: HTMLElement) { bind:value={searchTerm} oninput={handleInput} onfocus={handleFocus} - placeholder={m.comp_typeahead_placeholder()} + placeholder={placeholder ?? m.comp_typeahead_placeholder()} class="mt-1 block w-full rounded-md border border-line p-2 shadow-sm focus:border-accent focus:ring-accent" /> diff --git a/frontend/src/routes/korrespondenz/+page.svelte b/frontend/src/routes/korrespondenz/+page.svelte index d29e442d..3b06de06 100644 --- a/frontend/src/routes/korrespondenz/+page.svelte +++ b/frontend/src/routes/korrespondenz/+page.svelte @@ -76,53 +76,49 @@ function swapPersons() { } function selectPerson(id: string) { + if (!id) { + document.querySelector('#senderId-search')?.focus(); + return; + } senderId = id; receiverId = ''; applyFilters(); } -
- -
-

{m.conv_heading()}

-

- {m.conv_subtitle()} -

-
+ + - - + + + +{#if isSinglePerson} + +{/if} - - - - - {#if isSinglePerson} - - {/if} - - + +
{#if !senderId} {:else if data.documents.length === 0} diff --git a/frontend/src/routes/korrespondenz/ConversationTimeline.svelte b/frontend/src/routes/korrespondenz/ConversationTimeline.svelte index 1eedcd68..cf52312f 100644 --- a/frontend/src/routes/korrespondenz/ConversationTimeline.svelte +++ b/frontend/src/routes/korrespondenz/ConversationTimeline.svelte @@ -51,6 +51,9 @@ const outPct = $derived(documents.length > 0 ? (outCount / documents.length) * 1 const isBilateral = $derived(!!senderId && !!receiverId); +const shortSenderName = $derived(senderName?.split(' ')[0] ?? senderName ?? ''); +const shortReceiverName = $derived(receiverName?.split(' ')[0] ?? receiverName ?? ''); + function statusDotClass(status: string): string { const map: Record = { PLACEHOLDER: 'bg-yellow-400', @@ -82,8 +85,8 @@ const newDocUrl = $derived( aria-label="Briefverteilung in diesem Zeitraum: {outCount} von {senderName ?? ''}, {inCount} von {receiverName ?? ''}" >
- {outCount} von {senderName} → - {inCount} von {receiverName} ← + {outCount} von {shortSenderName} → + {inCount} von {shortReceiverName} ←
diff --git a/frontend/src/routes/korrespondenz/CorrespondenzPersonBar.svelte b/frontend/src/routes/korrespondenz/CorrespondenzPersonBar.svelte index 1a3b22ba..ada7d11f 100644 --- a/frontend/src/routes/korrespondenz/CorrespondenzPersonBar.svelte +++ b/frontend/src/routes/korrespondenz/CorrespondenzPersonBar.svelte @@ -1,5 +1,6 @@
@@ -42,7 +55,6 @@ let swapVisible = $derived(!!(senderId && receiverId)); aria-label="Personen tauschen" onclick={onswapPersons} class="mb-1 flex h-7 w-7 shrink-0 items-center justify-center rounded border border-[#D1D5DB] bg-white text-[#888] transition-colors hover:border-[#002850] hover:text-[#002850]" - class:opacity-0={!swapVisible} class:pointer-events-none={!swapVisible} tabindex={swapVisible ? 0 : -1} > @@ -65,23 +77,31 @@ let swapVisible = $derived(!!(senderId && receiverId));
onapplyFilters()} + onchange={() => { + showSuggestions = false; + onapplyFilters(); + }} + onfocused={handleCorrespondentFocused} /> - {#if !receiverId} - - — optional - + {#if showSuggestions && senderId && !receiverId} + (showSuggestions = false)} + /> {/if}
diff --git a/frontend/src/routes/korrespondenz/SinglePersonHintBar.svelte b/frontend/src/routes/korrespondenz/SinglePersonHintBar.svelte index 9bb49308..e643e7eb 100644 --- a/frontend/src/routes/korrespondenz/SinglePersonHintBar.svelte +++ b/frontend/src/routes/korrespondenz/SinglePersonHintBar.svelte @@ -1,10 +1,5 @@