From f85f2fbcc278eca3efccd2ee6db3c54001008ab6 Mon Sep 17 00:00:00 2001 From: Dotta Date: Sat, 7 Mar 2026 09:57:50 -0600 Subject: [PATCH] feat(ui): add copy-as-markdown button to comment headers Adds a small copy icon to the right of each comment's date that copies the comment body as raw markdown to the clipboard. Shows a checkmark briefly after copying. Co-Authored-By: Claude Opus 4.6 --- ui/src/components/CommentThread.tsx | 36 +++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/ui/src/components/CommentThread.tsx b/ui/src/components/CommentThread.tsx index f529382b..fa123d31 100644 --- a/ui/src/components/CommentThread.tsx +++ b/ui/src/components/CommentThread.tsx @@ -2,7 +2,7 @@ import { memo, useEffect, useMemo, useRef, useState, type ChangeEvent } from "re import { Link, useLocation } from "react-router-dom"; import type { IssueComment, Agent } from "@paperclipai/shared"; import { Button } from "@/components/ui/button"; -import { Paperclip } from "lucide-react"; +import { Check, Copy, Paperclip } from "lucide-react"; import { Identity } from "./Identity"; import { InlineEntitySelector, type InlineEntityOption } from "./InlineEntitySelector"; import { MarkdownBody } from "./MarkdownBody"; @@ -92,6 +92,25 @@ function parseReassignment(target: string): CommentReassignment | null { return null; } +function CopyMarkdownButton({ text }: { text: string }) { + const [copied, setCopied] = useState(false); + return ( + + ); +} + type TimelineItem = | { kind: "comment"; id: string; createdAtMs: number; comment: CommentWithRunMeta } | { kind: "run"; id: string; createdAtMs: number; run: LinkedRunItem }; @@ -160,12 +179,15 @@ const TimelineList = memo(function TimelineList({ ) : ( )} - - {formatDateTime(comment.createdAt)} - + + + {formatDateTime(comment.createdAt)} + + + {comment.body} {comment.runId && (