Files
boocode/apps/web/src/components/AttachmentChip.tsx
indifferentketchup c35ec65fc4 batch4: chats-in-sessions, force-send, /compact, right-rail file browser
Session 1:N Chat data model with backfill. Workspace switches to client-side
multi-tab pane management. Right-rail file browser with float-over viewer and
click-drag line selection replaces FileBrowserPane. Adds /compact streaming
summarizer (respects compact markers in context builder), force-send (cancels
in-flight, persists partial as 'cancelled', awaits cancellation completion via
deferred Promise + 5s timeout), message queue, stop generation, chat
auto-rename, session archive/unarchive with Closed Sessions section on repo
landing page. CHECK constraints on sessions.status, messages.role,
messages.status with KEEP IN SYNC comments tying to MESSAGE_ROLES /
MESSAGE_STATUSES const arrays. Deletes dead pane routes/hook and the
api.panes.* client block.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 20:39:48 +00:00

42 lines
1.4 KiB
TypeScript

import { FileText, X } from 'lucide-react';
import type { Attachment } from '@/lib/attachments';
interface Props {
attachment: Attachment;
onRemove: (id: string) => void;
onPreview: (attachment: Attachment) => void;
}
export function AttachmentChip({ attachment, onRemove, onPreview }: Props) {
const lineCount = attachment.content.split('\n').length;
const label =
attachment.kind === 'lines' && attachment.range
? `${attachment.filename}:${attachment.range[0]}-${attachment.range[1]}`
: attachment.filename;
return (
<div className="flex items-center gap-1.5 bg-muted/60 border border-border rounded px-2 py-0.5 text-xs font-mono">
<button
type="button"
onClick={() => onPreview(attachment)}
className="flex items-center gap-1.5 hover:bg-muted/60 transition-colors min-w-0"
>
<FileText className="size-3 shrink-0 text-muted-foreground" />
<span className="truncate max-w-[200px]">{label}</span>
<span className="text-muted-foreground whitespace-nowrap">
+{lineCount} lines
</span>
</button>
<button
type="button"
onClick={() => onRemove(attachment.id)}
className="ml-0.5 rounded hover:bg-muted-foreground/20 p-0.5 shrink-0"
aria-label="Remove attachment"
>
<X className="size-3" />
</button>
</div>
);
}