authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-04-02 00:47:47-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-04-02 00:47:47-07:00
log60f7ae86bbeaa95ebdfeb0fd83edc564119258df
treee9c2e25d26dcc594ba2631a2d1294506bbf4b0a7
parent867cf4cf091b2626930e58d46c9fee9f009b6916
signature Signed by PGP key B5690EEEBB952194

Add copy-to-clipboard action for proposed plan card (#1620)

Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>

1 files changed, 17 insertions(+), 0 deletions(-)

apps/web/src/components/chat/ProposedPlanCard.tsx+17
......@@ -25,6 +25,7 @@ import {
2525} from "../ui/dialog";
2626import { toastManager } from "../ui/toast";
2727import { readNativeApi } from "~/nativeApi";
28import { useCopyToClipboard } from "~/hooks/useCopyToClipboard";
2829
2930export const ProposedPlanCard = memo(function ProposedPlanCard({
3031 planMarkdown,
......@@ -39,6 +40,15 @@ export const ProposedPlanCard = memo(function ProposedPlanCard({
3940 const [isSaveDialogOpen, setIsSaveDialogOpen] = useState(false);
4041 const [savePath, setSavePath] = useState("");
4142 const [isSavingToWorkspace, setIsSavingToWorkspace] = useState(false);
43 const { copyToClipboard, isCopied } = useCopyToClipboard({
44 onError: (error) => {
45 toastManager.add({
46 type: "error",
47 title: "Could not copy plan",
48 description: error instanceof Error ? error.message : "An error occurred while copying.",
49 });
50 },
51 });
4252 const savePathInputId = useId();
4353 const title = proposedPlanTitle(planMarkdown) ?? "Proposed plan";
4454 const lineCount = planMarkdown.split("\n").length;
......@@ -54,6 +64,10 @@ export const ProposedPlanCard = memo(function ProposedPlanCard({
5464 downloadPlanAsTextFile(downloadFilename, saveContents);
5565 };
5666
67 const handleCopyPlan = () => {
68 copyToClipboard(saveContents);
69 };
70
5771 const openSaveDialog = () => {
5872 if (!workspaceRoot) {
5973 toastManager.add({
......@@ -127,6 +141,9 @@ export const ProposedPlanCard = memo(function ProposedPlanCard({
127141 <EllipsisIcon aria-hidden="true" className="size-4" />
128142 </MenuTrigger>
129143 <MenuPopup align="end">
144 <MenuItem onClick={handleCopyPlan}>
145 {isCopied ? "Copied!" : "Copy to clipboard"}
146 </MenuItem>
130147 <MenuItem onClick={handleDownload}>Download as markdown</MenuItem>
131148 <MenuItem onClick={openSaveDialog} disabled={!workspaceRoot || isSavingToWorkspace}>
132149 Save to workspace