feat(ui): add collapsible PDF strip and abbreviated labels on mobile
Some checks failed
CI / Unit & Component Tests (push) Failing after 2s
CI / Backend Unit Tests (push) Failing after 2s
CI / Unit & Component Tests (pull_request) Failing after 3s
CI / Backend Unit Tests (pull_request) Failing after 1s

PDF viewer collapses to 70px on mobile in read mode, expandable to
50vh. Toggle button with chevron. Paragraph tap auto-expands strip.
Mode toggle abbreviates to "Bearb." on small screens.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-07 11:30:36 +02:00
parent 10cecb01f5
commit 4d5b8b4ead
2 changed files with 32 additions and 5 deletions

View File

@@ -54,12 +54,13 @@ function handleReadClick() {
? 'bg-primary text-primary-fg'
: 'text-ink-2 hover:text-ink'}"
>
{m.mode_edit()}
<span class="md:hidden">{m.mode_edit_short()}</span>
<span class="hidden md:inline">{m.mode_edit()}</span>
</button>
</div>
<!-- Status line -->
<p class="text-xs text-ink-2">
<!-- Status line (hidden on mobile to save space) -->
<p class="hidden text-xs text-ink-2 md:block">
{#if blockCount === 1}
{m.transcription_status_section()}
{:else}

View File

@@ -1,5 +1,6 @@
<script lang="ts">
import { onMount } from 'svelte';
import { m } from '$lib/paraglide/messages.js';
import DocumentTopBar from '$lib/components/DocumentTopBar.svelte';
import DocumentViewer from '$lib/components/DocumentViewer.svelte';
import TranscriptionEditView from '$lib/components/TranscriptionEditView.svelte';
@@ -55,6 +56,7 @@ let panelMode = $state<'read' | 'edit'>('read');
let activeAnnotationId = $state<string | null>(null);
let highlightBlockId = $state<string | null>(null);
let flashAnnotationId = $state<string | null>(null);
let pdfStripExpanded = $state(false);
const prefersReducedMotion = $derived(
typeof window !== 'undefined' && window.matchMedia('(prefers-reduced-motion: reduce)').matches
@@ -187,6 +189,7 @@ async function handleAnnotationClick(annotationId: string) {
function handleParagraphClick(annotationId: string) {
activeAnnotationId = annotationId;
flashAnnotationId = annotationId;
pdfStripExpanded = true;
setTimeout(
() => {
flashAnnotationId = null;
@@ -246,7 +249,9 @@ onMount(() => {
<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'}
class={transcribeMode
? `relative flex-1 overflow-hidden md:min-h-0 ${panelMode === 'read' ? (pdfStripExpanded ? 'max-h-[50vh] min-h-[50vh] md:max-h-none md:min-h-0' : 'max-h-[70px] min-h-[70px] md:max-h-none md:min-h-0') : 'min-h-[40vh]'} transition-[min-height,max-height] duration-300`
: 'absolute inset-0'}
>
<DocumentViewer
doc={doc}
@@ -264,9 +269,30 @@ onMount(() => {
/>
</div>
{#if transcribeMode && panelMode === 'read'}
<button
type="button"
onclick={() => (pdfStripExpanded = !pdfStripExpanded)}
class="flex h-7 w-full shrink-0 items-center justify-center border-t border-line bg-muted text-xs font-semibold text-ink-2 md:hidden"
aria-label={pdfStripExpanded ? m.scan_collapse() : m.scan_expand()}
>
<svg
class="mr-1 h-3 w-3 transition-transform duration-200 {pdfStripExpanded ? 'rotate-180' : ''}"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2.5"
aria-hidden="true"
>
<path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" />
</svg>
{pdfStripExpanded ? m.scan_collapse() : m.scan_expand()}
</button>
{/if}
{#if transcribeMode}
<div
class="flex shrink-0 flex-col border-t border-line md:w-[400px] md:border-t-0 md:border-l lg:w-[480px]"
class="flex min-h-0 flex-1 shrink-0 flex-col border-t border-line md:w-[400px] md:flex-none md:border-t-0 md:border-l lg:w-[480px]"
>
<TranscriptionPanelHeader
mode={panelMode}