diff --git a/frontend/src/components/CopyButton.tsx b/frontend/src/components/CopyButton.tsx new file mode 100644 index 00000000..e28fdcaf --- /dev/null +++ b/frontend/src/components/CopyButton.tsx @@ -0,0 +1,45 @@ +import { useState } from 'react'; +import Copy from './../assets/copy.svg?react'; +import CheckMark from './../assets/checkmark.svg?react'; +import copy from 'copy-to-clipboard'; + +export default function CoppyButton({ text }: { text: string }) { + const [copied, setCopied] = useState(false); + const [isCopyHovered, setIsCopyHovered] = useState(false); + + const handleCopyClick = (text: string) => { + copy(text); + setCopied(true); + // Reset copied to false after a few seconds + setTimeout(() => { + setCopied(false); + }, 3000); + }; + + return ( +
+ {copied ? ( + setIsCopyHovered(true)} + onMouseLeave={() => setIsCopyHovered(false)} + /> + ) : ( + { + handleCopyClick(text); + }} + onMouseEnter={() => setIsCopyHovered(true)} + onMouseLeave={() => setIsCopyHovered(false)} + /> + )} +
+ ); +} diff --git a/frontend/src/conversation/ConversationBubble.tsx b/frontend/src/conversation/ConversationBubble.tsx index bce831f7..9877db66 100644 --- a/frontend/src/conversation/ConversationBubble.tsx +++ b/frontend/src/conversation/ConversationBubble.tsx @@ -1,15 +1,14 @@ import { forwardRef, useState } from 'react'; import Avatar from '../components/Avatar'; +import CoppyButton from '../components/CopyButton'; import remarkGfm from 'remark-gfm'; import { FEEDBACK, MESSAGE_TYPE } from './conversationModels'; import classes from './ConversationBubble.module.css'; import Alert from './../assets/alert.svg'; import Like from './../assets/like.svg?react'; import Dislike from './../assets/dislike.svg?react'; -import Copy from './../assets/copy.svg?react'; -import CheckMark from './../assets/checkmark.svg?react'; + import ReactMarkdown from 'react-markdown'; -import copy from 'copy-to-clipboard'; import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; import { vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism'; import DocsGPT3 from '../assets/cute_docsgpt3.svg'; @@ -30,29 +29,19 @@ const ConversationBubble = forwardRef< ref, ) { const [openSource, setOpenSource] = useState(null); - const [copied, setCopied] = useState(false); - const handleCopyClick = (text: string) => { - copy(text); - setCopied(true); - // Reset copied to false after a few seconds - setTimeout(() => { - setCopied(false); - }, 3000); - }; - const [isCopyHovered, setIsCopyHovered] = useState(false); const [isLikeHovered, setIsLikeHovered] = useState(false); const [isDislikeHovered, setIsDislikeHovered] = useState(false); const [isLikeClicked, setIsLikeClicked] = useState(false); const [isDislikeClicked, setIsDislikeClicked] = useState(false); let bubble; - + if (type === 'QUESTION') { bubble = (
-
+
{message} @@ -95,14 +84,24 @@ const ConversationBubble = forwardRef< const match = /language-(\w+)/.exec(className || ''); return !inline && match ? ( - - {String(children).replace(/\n$/, '')} - +
+ + {String(children).replace(/\n$/, '')} + +
+ +
+
) : ( {children} @@ -172,7 +171,7 @@ const ConversationBubble = forwardRef< {sources?.map((source, index) => (
-
- {copied ? ( - setIsCopyHovered(true)} - onMouseLeave={() => setIsCopyHovered(false)} - /> - ) : ( - { - handleCopyClick(message); - }} - onMouseEnter={() => setIsCopyHovered(true)} - onMouseLeave={() => setIsCopyHovered(false)} - > - )} -
+