diff --git a/package.json b/package.json index f6879be7..48818471 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "eslint": "8.36.0", "eslint-config-next": "13.2.4", "eventsource-parser": "^1.0.0", + "framer-motion": "^10.12.22", "next": "13.2.4", "openai": "^3.2.1", "parse-numeric-range": "^1.3.0", diff --git a/src/components/chat/ChatMessage.tsx b/src/components/chat/ChatMessage.tsx index 6363e87b..54d52b2b 100644 --- a/src/components/chat/ChatMessage.tsx +++ b/src/components/chat/ChatMessage.tsx @@ -1,9 +1,15 @@ -import { useOpenAI } from "@/context/OpenAIProvider"; +import { motion } from "framer-motion"; import { OpenAIChatMessage } from "@/utils/OpenAI"; import React from "react"; -import { MdPerson, MdSmartToy } from "react-icons/md"; +import { + MdPerson, + MdSmartToy, + MdContentCopy, + MdCheckCircle, +} from "react-icons/md"; import AssistantMessageContent from "./AssistantMessageContent"; import UserMessageContent from "./UserMessageContent"; +import useCopyToClipboard from "../hooks/useCopyToClipboard"; type Props = { message: OpenAIChatMessage; @@ -11,6 +17,7 @@ type Props = { export default function ChatMessage({ message: { id, role, content } }: Props) { const [hover, setHover] = React.useState(false); + const [copied, handleCopy] = useCopyToClipboard(content); return (
setHover(true)} onMouseLeave={() => setHover(false)} > -
+
{role === "user" ? : }
-
+
{role === "user" ? ( ) : ( )}
+
+ {copied ? ( + + + + ) : ( + + )} +
diff --git a/src/components/hooks/useCopyToClipboard.ts b/src/components/hooks/useCopyToClipboard.ts new file mode 100644 index 00000000..03fc929b --- /dev/null +++ b/src/components/hooks/useCopyToClipboard.ts @@ -0,0 +1,27 @@ +import { useState, useEffect } from "react"; + +type UseCopyToClipboardOutput = [boolean, () => void]; + +const useCopyToClipboard = (textToCopy: string): UseCopyToClipboardOutput => { + const [copied, setCopied] = useState(false); + + const handleCopy = (): void => { + navigator.clipboard.writeText(textToCopy); + setCopied(true); + }; + + useEffect(() => { + if (copied) { + const timer = setTimeout(() => { + setCopied(false); + }, 2500); + + return () => clearTimeout(timer); + } + }, [copied]); + + return [copied, handleCopy]; +}; + +export default useCopyToClipboard; +