Revert "feat: copy messages on hoverable icon (#1492)" (#1508)

This commit is contained in:
Alex Hancock
2025-03-04 14:08:01 -05:00
committed by GitHub
parent 48838c91c4
commit 7b767abfe6
5 changed files with 25 additions and 59 deletions

View File

@@ -235,7 +235,7 @@ export default function ChatView({
{messages.length === 0 ? (
<Splash append={(text) => append(createUserMessage(text))} />
) : (
<ScrollArea ref={scrollRef} className="flex-1 pl-4" autoScroll>
<ScrollArea ref={scrollRef} className="flex-1 px-4" autoScroll>
{filteredMessages.map((message, index) => (
<div key={message.id || index} className="mt-[16px]">
{isUserMessage(message) ? (

View File

@@ -12,7 +12,6 @@ import {
getToolConfirmationContent,
} from '../types/message';
import ToolCallConfirmation from './ToolCallConfirmation';
import CopyButton from './ui/CopyButton';
interface GooseMessageProps {
message: Message;
@@ -68,17 +67,9 @@ export default function GooseMessage({ message, metadata, messages, append }: Go
{/* Always show the top content area if there are tool calls, even if textContent is empty */}
{(textContent || toolRequests.length > 0) && (
<div
className={`goose-message-content bg-bgSubtle rounded-2xl px-4 py-2 ${toolRequests.length > 0 ? 'rounded-b-none' : ''} relative group`}
className={`goose-message-content bg-bgSubtle rounded-2xl px-4 py-2 ${toolRequests.length > 0 ? 'rounded-b-none' : ''}`}
>
{textContent ? <MarkdownContent content={textContent} /> : null}
{/* Only show CopyButton if there's text content and no tool requests/responses */}
{textContent && message.content.every((content) => content.type === 'text') && (
<CopyButton
text={textContent}
className="absolute -bottom-2 -right-2 p-1.5 rounded-full bg-white dark:bg-gray-800 shadow-md z-[1000] hover:bg-gray-100 dark:hover:bg-gray-700 opacity-0 group-hover:opacity-100 transition-opacity"
iconClassName="h-4 w-4 text-gray-800 dark:text-white"
/>
)}
</div>
)}

View File

@@ -1,11 +1,12 @@
import React from 'react';
import React, { useState } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import rehypeRaw from 'rehype-raw';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
import { oneLight } from 'react-syntax-highlighter/dist/cjs/styles/prism';
import { Check, Copy } from './icons';
import { visit } from 'unist-util-visit';
import CopyButton from './ui/CopyButton';
const UrlTransform = {
a: ({ node, ...props }) => <a {...props} target="_blank" rel="noopener noreferrer" />,
@@ -30,14 +31,28 @@ interface MarkdownContentProps {
}
const CodeBlock = ({ language, children }: { language: string; children: string }) => {
const [copied, setCopied] = useState(false);
const handleCopy = async () => {
try {
await navigator.clipboard.writeText(children);
setCopied(true);
setTimeout(() => setCopied(false), 2000); // Reset after 2 seconds
} catch (err) {
console.error('Failed to copy text: ', err);
}
};
return (
<div className="relative group w-full">
<CopyButton
text={children}
<button
onClick={handleCopy}
className="absolute right-2 bottom-2 p-1.5 rounded-lg bg-gray-700/50 text-gray-300
opacity-0 group-hover:opacity-100 transition-opacity duration-200
hover:bg-gray-600/50 hover:text-gray-100 z-10"
/>
title="Copy code"
>
{copied ? <Check className="h-4 w-4" /> : <Copy className="h-4 w-4" />}
</button>
<div className="w-full overflow-x-auto">
<SyntaxHighlighter
style={oneDark}
@@ -64,6 +79,8 @@ const CodeBlock = ({ language, children }: { language: string; children: string
};
export default function MarkdownContent({ content, className = '' }: MarkdownContentProps) {
// Determine whether dark mode is enabled
const isDarkMode = document.documentElement.classList.contains('dark');
return (
<div className="w-full overflow-x-hidden">
<ReactMarkdown

View File

@@ -3,7 +3,6 @@ import LinkPreview from './LinkPreview';
import { extractUrls } from '../utils/urlUtils';
import MarkdownContent from './MarkdownContent';
import { Message, getTextContent } from '../types/message';
import CopyButton from './ui/CopyButton';
interface UserMessageProps {
message: Message;
@@ -19,13 +18,8 @@ export default function UserMessage({ message }: UserMessageProps) {
return (
<div className="flex justify-end mt-[16px] w-full opacity-0 animate-[appear_150ms_ease-in_forwards]">
<div className="flex-col max-w-[85%]">
<div className="flex bg-slate text-white rounded-xl rounded-br-none py-2 px-3 mr-4 relative group">
<div className="flex bg-slate text-white rounded-xl rounded-br-none py-2 px-3">
<MarkdownContent content={textContent} className="text-white" />
<CopyButton
text={textContent}
className="absolute -bottom-2 -right-2 p-1.5 rounded-full bg-white dark:bg-gray-800 shadow-md z-[1000] hover:bg-gray-100 dark:hover:bg-gray-700 opacity-0 group-hover:opacity-100 transition-opacity"
iconClassName="h-4 w-4 text-gray-800 dark:text-white"
/>
</div>
{/* TODO(alexhancock): Re-enable link previews once styled well again */}

View File

@@ -1,36 +0,0 @@
import React, { useState } from 'react';
import { Check, Copy } from '../icons';
interface CopyButtonProps {
text: string;
className?: string;
iconClassName?: string;
lightIcon?: boolean;
}
export default function CopyButton({
text,
className = 'absolute bottom-2 right-2 p-1.5 rounded-lg bg-gray-700/50 text-gray-300 opacity-0 group-hover:opacity-100 transition-opacity duration-200 hover:bg-gray-600/50 hover:text-gray-100',
iconClassName = 'h-4 w-4',
lightIcon = false,
}: CopyButtonProps) {
const [copied, setCopied] = useState(false);
const handleCopy = async () => {
try {
await navigator.clipboard.writeText(text);
setCopied(true);
setTimeout(() => setCopied(false), 2000); // Reset after 2 seconds
} catch (err) {
console.error('Failed to copy text: ', err);
}
};
const Icon = copied ? Check : Copy;
return (
<button onClick={handleCopy} className={className} title="Copy text">
<Icon className={`${iconClassName} ${lightIcon ? 'text-white' : ''}`} />
</button>
);
}