fix(ui): unify Briefwechsel search bar with document search card style
Wrap person bar + filter controls in a card matching the document search page (rounded-sm border p-6 shadow-sm). Switch PersonTypeahead to default mode with matching label/input overrides. Bump date inputs and sort button to text-sm py-2.5. Filter row uses border-t separator like the document search advanced section. Refs: #179 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -99,37 +99,39 @@ function selectPerson(id: string) {
|
||||
<CorrespondenzHero onSelectPerson={selectPerson} recentPersons={recentPersons} />
|
||||
</div>
|
||||
{:else}
|
||||
<!-- Results state: strips + content -->
|
||||
<!-- Results state: card + content -->
|
||||
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<CorrespondenzPersonBar
|
||||
bind:senderId={senderId}
|
||||
bind:receiverId={receiverId}
|
||||
initialSenderName={data.initialValues.senderName}
|
||||
initialReceiverName={data.initialValues.receiverName}
|
||||
onapplyFilters={applyFilters}
|
||||
onswapPersons={swapPersons}
|
||||
/>
|
||||
|
||||
<CorrespondenzFilterControls
|
||||
senderId={senderId}
|
||||
bind:fromDate={fromDate}
|
||||
bind:toDate={toDate}
|
||||
bind:sortDir={sortDir}
|
||||
documentCount={data.documents.length}
|
||||
onapplyFilters={applyFilters}
|
||||
ontoggleSort={toggleSort}
|
||||
/>
|
||||
|
||||
{#if isSinglePerson}
|
||||
<SinglePersonHintBar
|
||||
senderName={senderName}
|
||||
fromDate={fromDate || undefined}
|
||||
toDate={toDate || undefined}
|
||||
sortDir={sortDir}
|
||||
<div class="mb-8 rounded-sm border border-line bg-surface p-6 shadow-sm">
|
||||
<CorrespondenzPersonBar
|
||||
bind:senderId={senderId}
|
||||
bind:receiverId={receiverId}
|
||||
initialSenderName={data.initialValues.senderName}
|
||||
initialReceiverName={data.initialValues.receiverName}
|
||||
onapplyFilters={applyFilters}
|
||||
onswapPersons={swapPersons}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<div class="py-4">
|
||||
<CorrespondenzFilterControls
|
||||
senderId={senderId}
|
||||
bind:fromDate={fromDate}
|
||||
bind:toDate={toDate}
|
||||
bind:sortDir={sortDir}
|
||||
documentCount={data.documents.length}
|
||||
onapplyFilters={applyFilters}
|
||||
ontoggleSort={toggleSort}
|
||||
/>
|
||||
|
||||
{#if isSinglePerson}
|
||||
<SinglePersonHintBar
|
||||
senderName={senderName}
|
||||
fromDate={fromDate || undefined}
|
||||
toDate={toDate || undefined}
|
||||
sortDir={sortDir}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{#if data.documents.length === 0}
|
||||
<div
|
||||
class="flex flex-col items-center justify-center rounded-sm border border-line bg-muted py-24 text-center shadow-sm"
|
||||
|
||||
@@ -28,13 +28,13 @@ let isActive = $derived(!!(fromDate || toDate || sortDir !== 'DESC'));
|
||||
|
||||
<div
|
||||
data-testid="conv-filter-controls"
|
||||
class="flex items-center gap-[10px] border-b border-line bg-muted px-3 py-[5px] transition-opacity"
|
||||
class="mt-6 flex items-center gap-4 border-t border-line-2 pt-6 transition-opacity"
|
||||
class:opacity-40={!senderId}
|
||||
class:pointer-events-none={!senderId}
|
||||
aria-disabled={!senderId}
|
||||
>
|
||||
<!-- Period label -->
|
||||
<span class="hidden text-xs font-bold tracking-wide text-ink-3 uppercase sm:block">
|
||||
<span class="text-xs font-bold tracking-widest text-ink-2 uppercase">
|
||||
{m.conv_strip_period()}
|
||||
</span>
|
||||
|
||||
@@ -43,23 +43,23 @@ let isActive = $derived(!!(fromDate || toDate || sortDir !== 'DESC'));
|
||||
bind:value={fromDate}
|
||||
onchange={() => onapplyFilters()}
|
||||
placeholder={m.conv_strip_from_placeholder()}
|
||||
class="h-8 w-[100px] rounded border bg-surface px-2 text-xs text-ink focus:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring {fromDate ? 'border-primary' : 'border-line'}"
|
||||
class="w-[120px] border-line py-2.5 text-sm text-ink shadow-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring {fromDate ? 'border-primary' : 'border-line'}"
|
||||
/>
|
||||
|
||||
<span class="text-xs text-ink-3">–</span>
|
||||
<span class="text-sm text-ink-3">–</span>
|
||||
|
||||
<!-- To date -->
|
||||
<DateInput
|
||||
bind:value={toDate}
|
||||
onchange={() => onapplyFilters()}
|
||||
placeholder={m.conv_strip_to_placeholder()}
|
||||
class="h-8 w-[100px] rounded border bg-surface px-2 text-xs text-ink focus:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring {toDate ? 'border-primary' : 'border-line'}"
|
||||
class="w-[120px] border-line py-2.5 text-sm text-ink shadow-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring {toDate ? 'border-primary' : 'border-line'}"
|
||||
/>
|
||||
|
||||
<!-- Document count -->
|
||||
<span
|
||||
data-testid="conv-strip-count"
|
||||
class="ml-auto text-xs font-bold"
|
||||
class="ml-auto text-sm font-bold"
|
||||
class:text-primary={hasDateFilter}
|
||||
class:text-ink-3={!hasDateFilter}
|
||||
>
|
||||
@@ -73,18 +73,18 @@ let isActive = $derived(!!(fromDate || toDate || sortDir !== 'DESC'));
|
||||
aria-label="Sortierung umkehren"
|
||||
aria-pressed={sortDir === 'ASC'}
|
||||
onclick={ontoggleSort}
|
||||
class="flex h-8 min-h-[44px] items-center gap-1 rounded border px-3 text-xs font-bold"
|
||||
class="flex items-center gap-2 border px-4 py-2.5 text-sm font-bold tracking-wide uppercase transition hover:bg-muted hover:text-ink"
|
||||
class:border-primary={isActive}
|
||||
class:text-primary={isActive}
|
||||
class:border-line={!isActive}
|
||||
class:text-ink-3={!isActive}
|
||||
class:text-ink-2={!isActive}
|
||||
>
|
||||
{#if sortDir === 'ASC'}
|
||||
{m.conv_strip_sort_oldest()}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="10"
|
||||
height="10"
|
||||
width="12"
|
||||
height="12"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
@@ -99,8 +99,8 @@ let isActive = $derived(!!(fromDate || toDate || sortDir !== 'DESC'));
|
||||
{m.conv_strip_sort_newest()}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="10"
|
||||
height="10"
|
||||
width="12"
|
||||
height="12"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
|
||||
@@ -53,18 +53,16 @@ function handleSuggestionSelect(id: string) {
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
data-testid="conv-person-bar"
|
||||
class="flex items-end gap-[9px] border-b border-line bg-surface px-3 py-[9px] [&_input]:h-12"
|
||||
>
|
||||
<div data-testid="conv-person-bar" class="flex items-end gap-4">
|
||||
<!-- Person A -->
|
||||
<div class="min-w-0 flex-1">
|
||||
<div
|
||||
class="min-w-0 flex-1 [&_input]:border-line [&_input]:py-2.5 [&_label]:mb-2 [&_label]:text-xs [&_label]:font-bold [&_label]:tracking-widest [&_label]:text-ink-2 [&_label]:uppercase"
|
||||
>
|
||||
<PersonTypeahead
|
||||
name="senderId"
|
||||
label="Person"
|
||||
bind:value={senderId}
|
||||
initialName={initialSenderName}
|
||||
compact={true}
|
||||
restrictToCorrespondentsOf={receiverId || undefined}
|
||||
onchange={() => onapplyFilters()}
|
||||
/>
|
||||
@@ -76,7 +74,7 @@ function handleSuggestionSelect(id: string) {
|
||||
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="mb-[3px] flex items-center justify-center rounded border border-line bg-muted px-3 py-2.5 text-ink-3 transition-colors hover:border-primary hover:text-primary"
|
||||
class:opacity-0={!swapVisible}
|
||||
class:pointer-events-none={!swapVisible}
|
||||
tabindex={swapVisible ? 0 : -1}
|
||||
@@ -100,7 +98,7 @@ function handleSuggestionSelect(id: string) {
|
||||
|
||||
<!-- Korrespondent field -->
|
||||
<div
|
||||
class="relative min-w-0 flex-1"
|
||||
class="relative min-w-0 flex-1 [&_input]:border-line [&_input]:py-2.5 [&_label]:mb-2 [&_label]:text-xs [&_label]:font-bold [&_label]:tracking-widest [&_label]:text-ink-2 [&_label]:uppercase"
|
||||
class:[&_input]:border-dashed={!receiverId}
|
||||
class:[&_input]:border-solid={!!receiverId}
|
||||
class:[&_input]:bg-canvas={!receiverId}
|
||||
@@ -110,7 +108,6 @@ function handleSuggestionSelect(id: string) {
|
||||
label={receiverId ? 'Korrespondent' : 'Korrespondent — optional'}
|
||||
bind:value={receiverId}
|
||||
initialName={initialReceiverName}
|
||||
compact={true}
|
||||
placeholder="Alle Korrespondenten"
|
||||
restrictToCorrespondentsOf={senderId || undefined}
|
||||
onchange={() => {
|
||||
|
||||
@@ -19,7 +19,7 @@ let toYear = $derived(toDate ? toDate.substring(0, 4) : '');
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="flex items-center gap-[5px] border-b border-accent bg-accent-bg px-3 py-[6px] text-xs text-ink"
|
||||
class="mt-4 flex items-center gap-1.5 rounded-sm border border-accent bg-accent-bg px-4 py-2.5 text-sm text-ink"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
||||
Reference in New Issue
Block a user