feat(frontend): move annotation comments to right-side panel
Annotation threads now open in a slide-in side panel (320 px, right edge of the PDF viewer) instead of expanding the bottom drawer. The PDF stays visible while the user reads and writes annotation comments. - Add AnnotationSidePanel component (absolute-positioned, CSS slide transition, keyed CommentThread, close via X or Escape) - Remove the $effect that opened the bottom drawer on annotation click - Simplify PanelDiscussion back to document-level thread only (no annotation sub-tabs) - Remove annotation-related props from DocumentBottomPanel and PanelDiscussion Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
<script lang="ts">
|
||||
import { m } from '$lib/paraglide/messages.js';
|
||||
import CommentThread from './CommentThread.svelte';
|
||||
|
||||
type CommentReply = {
|
||||
@@ -23,107 +22,21 @@ type Comment = {
|
||||
|
||||
type Props = {
|
||||
documentId: string;
|
||||
activeAnnotationId: string | null;
|
||||
activeAnnotationPage: number | null;
|
||||
initialComments: Comment[];
|
||||
canComment: boolean;
|
||||
currentUserId: string | null;
|
||||
canAdmin: boolean;
|
||||
onAnnotationCommentCountChange?: (annotationId: string, count: number) => void;
|
||||
};
|
||||
|
||||
let {
|
||||
documentId,
|
||||
activeAnnotationId,
|
||||
activeAnnotationPage,
|
||||
initialComments,
|
||||
canComment,
|
||||
currentUserId,
|
||||
canAdmin,
|
||||
onAnnotationCommentCountChange
|
||||
}: Props = $props();
|
||||
|
||||
// Sub-tab within the discussion panel: 'document' or 'annotation'
|
||||
type DiscussionTab = 'document' | 'annotation';
|
||||
let activeSubTab = $state<DiscussionTab>('document');
|
||||
|
||||
// Track document-level comment count for badge.
|
||||
// CommentThread calls onCountChange immediately on mount with the accurate total.
|
||||
let docCommentCount = $state(0);
|
||||
|
||||
// When an annotation becomes active, switch to the annotation sub-tab automatically.
|
||||
$effect(() => {
|
||||
if (activeAnnotationId) {
|
||||
activeSubTab = 'annotation';
|
||||
} else {
|
||||
activeSubTab = 'document';
|
||||
}
|
||||
});
|
||||
|
||||
function selectDocumentTab() {
|
||||
activeSubTab = 'document';
|
||||
}
|
||||
|
||||
function selectAnnotationTab() {
|
||||
activeSubTab = 'annotation';
|
||||
}
|
||||
let { documentId, initialComments, canComment, currentUserId, canAdmin }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class="flex h-full flex-col">
|
||||
<!-- Sub-tab bar (only shown when annotation is active) -->
|
||||
{#if activeAnnotationId}
|
||||
<div class="flex shrink-0 border-b border-brand-sand/70 bg-gray-50 px-4">
|
||||
<button
|
||||
onclick={selectDocumentTab}
|
||||
class="mr-1 px-3 py-2 font-sans text-xs font-medium transition-colors {activeSubTab === 'document'
|
||||
? 'border-b-2 border-brand-navy text-brand-navy'
|
||||
: 'text-gray-400 hover:text-brand-navy'}"
|
||||
>
|
||||
{m.doc_panel_tab_discussion()}
|
||||
{#if docCommentCount > 0}
|
||||
<span
|
||||
class="ml-1 inline-flex h-4 min-w-4 items-center justify-center rounded-full bg-brand-mint px-1 font-mono text-[10px] text-brand-navy"
|
||||
>
|
||||
{docCommentCount}
|
||||
</span>
|
||||
{/if}
|
||||
</button>
|
||||
<button
|
||||
onclick={selectAnnotationTab}
|
||||
class="px-3 py-2 font-sans text-xs font-medium transition-colors {activeSubTab === 'annotation'
|
||||
? 'border-b-2 border-brand-navy text-brand-navy'
|
||||
: 'text-gray-400 hover:text-brand-navy'}"
|
||||
>
|
||||
{m.doc_panel_discussion_annotation_tab({ page: String(activeAnnotationPage ?? '?') })}
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Content area -->
|
||||
<div class="flex-1 overflow-y-auto p-6">
|
||||
{#if !activeAnnotationId || activeSubTab === 'document'}
|
||||
<!-- Document-level thread -->
|
||||
<CommentThread
|
||||
documentId={documentId}
|
||||
initialComments={initialComments}
|
||||
canComment={canComment}
|
||||
currentUserId={currentUserId}
|
||||
canAdmin={canAdmin}
|
||||
onCountChange={(count) => (docCommentCount = count)}
|
||||
/>
|
||||
{:else}
|
||||
<!-- Annotation-level thread -->
|
||||
{#key activeAnnotationId}
|
||||
<CommentThread
|
||||
documentId={documentId}
|
||||
annotationId={activeAnnotationId}
|
||||
canComment={canComment}
|
||||
currentUserId={currentUserId}
|
||||
canAdmin={canAdmin}
|
||||
loadOnMount={true}
|
||||
onCountChange={(count) => onAnnotationCommentCountChange?.(activeAnnotationId, count)}
|
||||
/>
|
||||
{/key}
|
||||
{/if}
|
||||
</div>
|
||||
<div class="flex-1 overflow-y-auto p-6">
|
||||
<CommentThread
|
||||
documentId={documentId}
|
||||
initialComments={initialComments}
|
||||
canComment={canComment}
|
||||
currentUserId={currentUserId}
|
||||
canAdmin={canAdmin}
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user