feat(topbar): add expandable metadata drawer with Details toggle (#175)
- DocumentMetadataDrawer: 3-column grid (≥1024px), single-column mobile
Shows document date, location, status, person cards, tag chips
Person names link to /persons/{id}, tags link to filtered search
Empty states for missing persons/tags, receiver cap with expand button
- DocumentTopBar: "Details" toggle button with animated SVG chevron
44×44px tap target, aria-expanded, Svelte slide transition
Semantic color tokens for dark mode compatibility
- Remove DocumentBottomPanel from document detail page
Bottom panel replaced by topbar drawer for metadata access
Simplify +page.server.ts (remove comments loading)
Update page.server.spec.ts for new load signature
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,9 +3,7 @@ import { onMount } from 'svelte';
|
||||
import { page } from '$app/state';
|
||||
import DocumentTopBar from '$lib/components/DocumentTopBar.svelte';
|
||||
import DocumentViewer from '$lib/components/DocumentViewer.svelte';
|
||||
import DocumentBottomPanel from '$lib/components/DocumentBottomPanel.svelte';
|
||||
import AnnotationSidePanel from '$lib/components/AnnotationSidePanel.svelte';
|
||||
import type { DocumentPanelTab } from '$lib/types';
|
||||
|
||||
let { data } = $props();
|
||||
|
||||
@@ -62,38 +60,17 @@ let annotateMode = $state(false);
|
||||
let activeAnnotationId = $state<string | null>(null);
|
||||
let activeAnnotationPage = $state<number | null>(null);
|
||||
|
||||
// Close the panel when entering annotate mode so the PDF is fully visible.
|
||||
$effect(() => {
|
||||
if (annotateMode) panelOpen = false;
|
||||
});
|
||||
// ── Navigation / init ─────────────────────────────────────────────────────────
|
||||
|
||||
// ── Bottom panel state ────────────────────────────────────────────────────────
|
||||
|
||||
let panelOpen = $state(false);
|
||||
let panelHeight = $state(0); // set to full height on mount
|
||||
let navHeight = $state(0);
|
||||
let activeTab = $state<DocumentPanelTab>('metadata');
|
||||
|
||||
onMount(() => {
|
||||
navHeight = document.querySelector('header')?.getBoundingClientRect().height ?? 0;
|
||||
|
||||
const topbar = document.querySelector('[data-topbar]');
|
||||
panelHeight = window.innerHeight - navHeight - (topbar?.getBoundingClientRect().height ?? 0);
|
||||
|
||||
if (targetAnnotationId) {
|
||||
// Deep-link into an annotation comment: open the side panel
|
||||
activeAnnotationId = targetAnnotationId;
|
||||
} else if (targetCommentId) {
|
||||
// Deep-link into a document-level comment: open discussion tab
|
||||
panelOpen = true;
|
||||
activeTab = 'discussion';
|
||||
} else if (!doc?.filePath) {
|
||||
// No file yet — open to metadata so the panel is immediately useful.
|
||||
panelOpen = true;
|
||||
activeTab = 'metadata';
|
||||
}
|
||||
|
||||
// Track last-visited document for the dashboard resume strip
|
||||
if (doc?.id) {
|
||||
localStorage.setItem(
|
||||
'familienarchiv.lastVisited',
|
||||
@@ -106,8 +83,6 @@ onMount(() => {
|
||||
if (activeAnnotationId) {
|
||||
activeAnnotationId = null;
|
||||
activeAnnotationPage = null;
|
||||
} else if (panelOpen) {
|
||||
panelOpen = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -160,16 +135,4 @@ onMount(() => {
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<DocumentBottomPanel
|
||||
doc={doc}
|
||||
comments={(data.comments ?? []) as never[]}
|
||||
canComment={canComment}
|
||||
currentUserId={currentUserId}
|
||||
canAdmin={canAdmin}
|
||||
targetCommentId={targetCommentId}
|
||||
bind:open={panelOpen}
|
||||
bind:height={panelHeight}
|
||||
bind:activeTab={activeTab}
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user