Files
vercel__workflow/docs/components/geistdocs/copy-chat.tsx
Hayden Bleasel c0991b4ff7 Update docs (#349)
* Initial migration

* Remove ExperimentalPackageCallout

* Remove Callout imports

* Add missing dep

* Update postgres-world.mdx

* Add missing deps, remove unused files

* Restore homepage css

* Update logo, fix homepage

* Update run-anywhere.tsx

* Remove duplicate h1 tags

* Fix package install commands

* Update global.css

* Update code-block.tsx

* Fix framework descriptions

* Remove unused files

* Fix steps

* Update sidebar.tsx

* Remove excess horizontal rules

* Remove unused components

* Cleanup home code-block component

* Update route.ts

* Add missing feed dep

* Rename middleware to proxy

* Update next config

* Update route.tsx

* Move generateDefinition call into tsx

* Update page.tsx

* Update sidebar.tsx

* Update layout.tsx

* Remove unused files

* Fix nav

* Update route.ts

* Remove deprecated lint:links

* Load fonts locally

* Update layout.tsx

* Update route.ts

* Update Geistdocs

* Update hero.tsx

* Update search.tsx

* Update search.tsx

* docs: update url structure in chat tools example

* chore: replace gpt-5 reasoning with gpt-5.1

* docs: update instructions for llm to be more workflow-centric

* Revert "docs: update instructions for llm to be more workflow-centric"

This reverts commit 3852820988.

* Update pnpm-lock.yaml

* Update home-layout.tsx

* Update layout.tsx

* Update pnpm-workspace.yaml

---------

Co-authored-by: Adrian Lam <me@adriandlam.com>
2025-11-19 16:17:21 -08:00

57 lines
1.5 KiB
TypeScript

import type { UIMessage } from 'ai';
import { CheckIcon, CopyIcon } from 'lucide-react';
import { useState } from 'react';
import { toast } from 'sonner';
import { Button } from '@/components/ui/button';
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from '@/components/ui/tooltip';
export const CopyChat = ({ messages }: { messages: UIMessage[] }) => {
const [copied, setCopied] = useState(false);
const handleCopyChat = async () => {
const markdown = messages
.map((message) => {
const role = message.role === 'user' ? 'You' : 'AI';
const content = message.parts
.filter((part) => part.type === 'text')
.map((part) => part.text)
.join('\n');
return `**${role}:**\n${content}`;
})
.join('\n\n---\n\n');
try {
await navigator.clipboard.writeText(markdown);
toast.success('Chat copied to clipboard');
setCopied(true);
setTimeout(() => setCopied(false), 2000);
} catch (error) {
toast.error('Failed to copy chat', {
description: error instanceof Error ? error.message : 'Unknown error',
});
}
};
const Icon = copied ? CheckIcon : CopyIcon;
return (
<Tooltip>
<TooltipTrigger asChild>
<Button
disabled={messages.length === 0}
onClick={handleCopyChat}
size="icon-sm"
variant="ghost"
>
<Icon className="size-3.5" />
</Button>
</TooltipTrigger>
<TooltipContent>Copy chat</TooltipContent>
</Tooltip>
);
};