feat(transcription): mobile stacked layout + cross-page scroll-sync
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled

Mobile layout (< 768px):
- Split view stacks vertically: PDF top (min 40vh), blocks below
- Blocks panel gets border-top instead of border-left
- PDF remains interactive for drawing in stacked mode

Scroll-sync (block → PDF):
- Clicking a block sets activeAnnotationId
- PdfViewer effect watches activeAnnotationId, navigates to the
  annotation's page if different from current, then scrolls the
  annotation element into view (double-rAF for async render timing)
- Works across pages: block on page 3 navigates PDF to page 3

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-05 23:13:27 +02:00
parent c22f2e41b1
commit b4212f5e86
2 changed files with 27 additions and 3 deletions

View File

@@ -217,6 +217,26 @@ $effect(() => {
if (transcribeMode) showAnnotations = true;
});
// Scroll-sync: when activeAnnotationId changes, navigate to its page
$effect(() => {
if (!activeAnnotationId || !pdfDoc) return;
const ann = annotations.find((a) => a.id === activeAnnotationId);
if (!ann) return;
if (ann.pageNumber !== currentPage) {
currentPage = ann.pageNumber;
}
// After page renders, scroll the annotation into view (double-rAF for async render)
const targetId = activeAnnotationId;
requestAnimationFrame(() => {
requestAnimationFrame(() => {
const el = document.querySelector(`[data-testid="annotation-${targetId}"]`);
el?.scrollIntoView({ behavior: 'smooth', block: 'center' });
});
});
});
function prevPage() {
if (currentPage > 1) currentPage -= 1;
}

View File

@@ -197,8 +197,10 @@ onMount(() => {
bind:transcribeMode={transcribeMode}
/>
<div class="relative flex-1 overflow-hidden {transcribeMode ? 'flex' : ''}">
<div class={transcribeMode ? 'relative flex-1 overflow-hidden' : 'absolute inset-0'}>
<div class="relative flex-1 overflow-hidden {transcribeMode ? 'flex flex-col md:flex-row' : ''}">
<div
class={transcribeMode ? 'relative min-h-[40vh] flex-1 overflow-hidden md:min-h-0' : 'absolute inset-0'}
>
<DocumentViewer
doc={doc}
fileUrl={fileUrl}
@@ -213,7 +215,9 @@ onMount(() => {
</div>
{#if transcribeMode}
<div class="w-[400px] shrink-0 border-l border-line lg:w-[480px]">
<div
class="shrink-0 border-t border-line md:w-[400px] md:border-t-0 md:border-l lg:w-[480px]"
>
<TranscriptionEditView
documentId={doc.id}
blocks={transcriptionBlocks}