feat(ui): add TranscriptionReadView for flowing prose display

Renders transcription blocks as readable text with [unleserlich]/[...]
markers styled as italic muted text. Supports click-to-sync and
flash highlight for scroll-sync feedback.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-07 11:14:53 +02:00
parent 7d98081390
commit 306eef2e95
2 changed files with 171 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
<script lang="ts">
import type { TranscriptionBlockData } from '$lib/types';
import { splitByMarkers } from '$lib/utils/transcriptionMarkers';
interface Props {
blocks: TranscriptionBlockData[];
onParagraphClick: (annotationId: string) => void;
highlightBlockId?: string | null;
}
let { blocks, onParagraphClick, highlightBlockId = null }: Props = $props();
let sorted = $derived([...blocks].sort((a, b) => a.sortOrder - b.sortOrder));
</script>
<article class="px-6 py-8">
{#each sorted as block (block.id)}
<div
class="-mx-2 mb-6 cursor-pointer rounded-sm px-2 py-1 font-serif text-[16px] leading-[1.85] text-ink transition-colors hover:bg-[rgba(0,199,177,0.06)]"
class:flash-highlight={highlightBlockId === block.id}
data-block-id={block.id}
onclick={() => onParagraphClick(block.annotationId)}
role="button"
tabindex="0"
onkeydown={(e) => { if (e.key === 'Enter' || e.key === ' ') onParagraphClick(block.annotationId); }}
>
{#each splitByMarkers(block.text) as segment, i (i)}
{#if segment.type === 'marker'}
<em data-marker class="text-ink-2 italic">{segment.text}</em>
{:else}
{segment.text}
{/if}
{/each}
</div>
{/each}
</article>
<style>
@keyframes flash {
0% {
background-color: rgba(0, 199, 177, 0.18);
}
100% {
background-color: transparent;
}
}
.flash-highlight {
animation: flash 1.2s ease-out;
}
</style>