- Accent bar, h-12/h-14 responsive height, 44×44px back link touch target - PersonChipRow with sender→receivers chips, overflow pill button at ≥768px - DocumentStatusChip dot-only at ≥768px - Edit/annotate/download actions with annotateMode wiring - AnnotateHintStrip below main row when annotateMode active - status field added to Doc type Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
172 lines
5.4 KiB
Svelte
172 lines
5.4 KiB
Svelte
<script lang="ts">
|
||
import { m } from '$lib/paraglide/messages.js';
|
||
import { formatDate } from '$lib/utils/personFormat';
|
||
import PersonChipRow from './PersonChipRow.svelte';
|
||
import DocumentStatusChip from './DocumentStatusChip.svelte';
|
||
import AnnotateHintStrip from './AnnotateHintStrip.svelte';
|
||
import OverflowPillButton from './OverflowPillButton.svelte';
|
||
|
||
type DocumentStatus = 'PLACEHOLDER' | 'UPLOADED' | 'TRANSCRIBED' | 'REVIEWED' | 'ARCHIVED';
|
||
type Person = { id: string; firstName: string; lastName: string };
|
||
|
||
type Doc = {
|
||
id: string;
|
||
title?: string | null;
|
||
originalFilename?: string | null;
|
||
documentDate?: string | null;
|
||
status: DocumentStatus;
|
||
sender?: Person | null;
|
||
receivers?: Person[] | null;
|
||
filePath?: string | null;
|
||
contentType?: string | null;
|
||
};
|
||
|
||
type Props = {
|
||
doc: Doc;
|
||
canWrite: boolean;
|
||
canAnnotate: boolean;
|
||
fileUrl: string;
|
||
annotateMode: boolean;
|
||
};
|
||
|
||
let { doc, canWrite, canAnnotate, fileUrl, annotateMode = $bindable() }: Props = $props();
|
||
|
||
const isPdf = $derived(!!doc.filePath && doc.contentType?.startsWith('application/pdf'));
|
||
const receivers = $derived(doc.receivers ?? []);
|
||
const extraCount = $derived(Math.max(0, receivers.length - 2));
|
||
const overflowPersons = $derived(receivers.slice(2));
|
||
|
||
const shortDate = $derived(doc.documentDate ? formatDate(doc.documentDate, 'short') : null);
|
||
const longDate = $derived(doc.documentDate ? formatDate(doc.documentDate, 'long') : null);
|
||
</script>
|
||
|
||
<div data-topbar class="border-b border-line bg-surface shadow-sm">
|
||
<!-- Main row -->
|
||
<div class="flex h-12 shrink-0 items-center xs:h-14">
|
||
<!-- Accent bar -->
|
||
<div class="h-full w-[3px] shrink-0 bg-primary"></div>
|
||
|
||
<!-- Back link — 44×44px touch target -->
|
||
<a
|
||
href="/"
|
||
aria-label="Zurück zur Dokumentenliste"
|
||
class="group -ml-0.5 flex h-11 w-11 shrink-0 items-center justify-center rounded-full transition-colors hover:bg-muted focus-visible:ring-2 focus-visible:ring-primary"
|
||
>
|
||
<img
|
||
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Arrow/Arrow-Left-MD.svg"
|
||
alt=""
|
||
aria-hidden="true"
|
||
class="h-5 w-5"
|
||
/>
|
||
</a>
|
||
|
||
<!-- Divider -->
|
||
<div class="mx-2 h-6 w-px shrink-0 bg-line"></div>
|
||
|
||
<!-- Title + meta -->
|
||
<div class="min-w-0 flex-1 overflow-hidden">
|
||
<h1
|
||
class="truncate font-serif text-[11px] leading-tight text-ink lg:text-[13px]"
|
||
title={doc.title ?? doc.originalFilename ?? ''}
|
||
>
|
||
{doc.title || doc.originalFilename}
|
||
</h1>
|
||
{#if shortDate}
|
||
<p class="font-sans text-[10px] text-ink-2">
|
||
<span class="lg:hidden">{shortDate}</span>
|
||
<span class="hidden lg:inline">{longDate}</span>
|
||
</p>
|
||
{/if}
|
||
</div>
|
||
|
||
<!-- Chip row (≥375px) -->
|
||
<div class="mx-3 min-w-0 shrink-0">
|
||
<PersonChipRow
|
||
sender={doc.sender}
|
||
receivers={receivers}
|
||
abbreviated={true}
|
||
extraCount={extraCount}
|
||
/>
|
||
</div>
|
||
|
||
<!-- Overflow pill button (desktop) + status dot -->
|
||
{#if extraCount > 0}
|
||
<OverflowPillButton extraCount={extraCount} persons={overflowPersons} />
|
||
{/if}
|
||
|
||
<DocumentStatusChip status={doc.status} />
|
||
|
||
<!-- Action buttons -->
|
||
<div class="ml-2 flex shrink-0 items-center gap-1.5 pr-3 font-sans">
|
||
{#if canAnnotate && isPdf && !annotateMode}
|
||
<button
|
||
onclick={() => (annotateMode = true)}
|
||
aria-label={m.doc_panel_annotate()}
|
||
aria-pressed={false}
|
||
class="hidden items-center gap-1.5 rounded border border-primary px-3 py-1.5 font-sans text-xs font-medium text-ink transition hover:bg-primary hover:text-primary-fg focus-visible:ring-2 focus-visible:ring-primary md:flex"
|
||
>
|
||
<img
|
||
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Note/Note-Add-MD.svg"
|
||
alt=""
|
||
aria-hidden="true"
|
||
class="h-4 w-4"
|
||
/>
|
||
<span>{m.doc_panel_annotate()}</span>
|
||
</button>
|
||
{/if}
|
||
|
||
{#if canAnnotate && isPdf && annotateMode}
|
||
<button
|
||
onclick={() => (annotateMode = false)}
|
||
aria-label={m.doc_panel_annotate_stop()}
|
||
aria-pressed={true}
|
||
class="hidden items-center gap-1.5 rounded bg-primary px-3 py-1.5 font-sans text-xs font-medium text-primary-fg transition focus-visible:ring-2 focus-visible:ring-primary md:flex"
|
||
>
|
||
<img
|
||
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Note/Note-Add-MD.svg"
|
||
alt=""
|
||
aria-hidden="true"
|
||
class="h-4 w-4 invert"
|
||
/>
|
||
<span>{m.doc_panel_annotate_stop()}</span>
|
||
</button>
|
||
{/if}
|
||
|
||
{#if canWrite && !annotateMode}
|
||
<a
|
||
href="/documents/{doc.id}/edit"
|
||
aria-label={m.btn_edit()}
|
||
class="flex items-center gap-1.5 rounded border border-primary bg-transparent px-3 py-1.5 text-xs font-medium text-ink transition hover:bg-primary hover:text-primary-fg focus-visible:ring-2 focus-visible:ring-primary"
|
||
>
|
||
<img
|
||
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Edit-Content-MD.svg"
|
||
alt=""
|
||
aria-hidden="true"
|
||
class="h-4 w-4"
|
||
/>
|
||
<span class="hidden sm:inline">{m.btn_edit()}</span>
|
||
</a>
|
||
{/if}
|
||
|
||
{#if doc.filePath && !annotateMode}
|
||
<a
|
||
href={fileUrl}
|
||
download={doc.originalFilename}
|
||
class="hidden rounded border border-transparent bg-muted p-1.5 text-ink transition hover:bg-accent focus-visible:ring-2 focus-visible:ring-primary md:block"
|
||
title={m.doc_download_title()}
|
||
>
|
||
<img
|
||
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Download-MD.svg"
|
||
alt=""
|
||
aria-hidden="true"
|
||
class="h-5 w-5"
|
||
/>
|
||
</a>
|
||
{/if}
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Hint strip — only when annotateMode, only at ≥768px -->
|
||
<AnnotateHintStrip annotateMode={annotateMode} />
|
||
</div>
|