diff --git a/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/HistoricalMessage/index.jsx b/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/HistoricalMessage/index.jsx index a128e0195b6034e6d9a8c94840343bccb2c6780a..d9efd98cc83e4e632bfa190ac1e0fc803a6114e4 100644 --- a/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/HistoricalMessage/index.jsx +++ b/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/HistoricalMessage/index.jsx @@ -44,7 +44,7 @@ const HistoricalMessage = ({ </div> ) : ( <span - className={`flex flex-col gap-y-1 mt-2`} + className={`flex flex-col gap-y-1`} dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(renderMarkdown(message)), }} diff --git a/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/PromptReply/index.jsx b/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/PromptReply/index.jsx index 5c48e92246eed615ff2c18efb94b04b0326626eb..98d41a11c0e6dad862456e55dce301e098741f6f 100644 --- a/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/PromptReply/index.jsx +++ b/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/PromptReply/index.jsx @@ -21,7 +21,7 @@ const PromptReply = ({ <div className={`flex justify-center items-end w-full ${assistantBackgroundColor}`} > - <div className="py-8 px-4 w-full flex gap-x-5 md:max-w-[800px] flex-col"> + <div className="py-6 px-4 w-full flex gap-x-5 md:max-w-[800px] flex-col"> <div className="flex gap-x-5"> <WorkspaceProfileImage workspace={workspace} /> <div className="mt-3 ml-5 dot-falling"></div> @@ -36,7 +36,7 @@ const PromptReply = ({ <div className={`flex justify-center items-end w-full ${assistantBackgroundColor}`} > - <div className="py-8 px-4 w-full flex gap-x-5 md:max-w-[800px] flex-col"> + <div className="py-6 px-4 w-full flex gap-x-5 md:max-w-[800px] flex-col"> <div className="flex gap-x-5"> <WorkspaceProfileImage workspace={workspace} /> <span @@ -57,7 +57,7 @@ const PromptReply = ({ key={uuid} className={`flex justify-center items-end w-full ${assistantBackgroundColor}`} > - <div className="py-8 px-4 w-full flex gap-x-5 md:max-w-[800px] flex-col"> + <div className="py-6 px-4 w-full flex gap-x-5 md:max-w-[800px] flex-col"> <div className="flex gap-x-5"> <WorkspaceProfileImage workspace={workspace} /> <span diff --git a/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/index.jsx b/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/index.jsx index 8fa4815dc24a9ea494936c2fc5284907fb6c7210..902409e4977d08d9ac998441eea1a9204fe671cb 100644 --- a/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/index.jsx +++ b/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/index.jsx @@ -12,6 +12,36 @@ export default function ChatHistory({ history = [], workspace, sendCommand }) { const { showing, showModal, hideModal } = useManageWorkspaceModal(); const [isAtBottom, setIsAtBottom] = useState(true); const chatHistoryRef = useRef(null); + const [textSize, setTextSize] = useState("normal"); + + const getTextSizeClass = (size) => { + switch (size) { + case "small": + return "text-[12px]"; + case "large": + return "text-[18px]"; + default: + return "text-[14px]"; + } + }; + + useEffect(() => { + const storedTextSize = window.localStorage.getItem("anythingllm_text_size"); + if (storedTextSize) { + setTextSize(getTextSizeClass(storedTextSize)); + } + + const handleTextSizeChange = (event) => { + const size = event.detail; + setTextSize(getTextSizeClass(size)); + }; + + window.addEventListener("textSizeChange", handleTextSizeChange); + + return () => { + window.removeEventListener("textSizeChange", handleTextSizeChange); + }; + }, []); useEffect(() => { if (isAtBottom) scrollToBottom(); @@ -91,7 +121,7 @@ export default function ChatHistory({ history = [], workspace, sendCommand }) { return ( <div - className="markdown text-white/80 font-light text-sm h-full md:h-[83%] pb-[100px] pt-6 md:pt-0 md:pb-20 md:mx-0 overflow-y-scroll flex flex-col justify-start no-scroll" + className={`markdown text-white/80 font-light ${textSize} h-full md:h-[83%] pb-[100px] pt-6 md:pt-0 md:pb-20 md:mx-0 overflow-y-scroll flex flex-col justify-start no-scroll`} id="chat-history" ref={chatHistoryRef} > diff --git a/frontend/src/components/WorkspaceChat/ChatContainer/PromptInput/TextSizeMenu/index.jsx b/frontend/src/components/WorkspaceChat/ChatContainer/PromptInput/TextSizeMenu/index.jsx new file mode 100644 index 0000000000000000000000000000000000000000..645e943c0d2c0b2bbc7c57a5e9f56ebbef1551be --- /dev/null +++ b/frontend/src/components/WorkspaceChat/ChatContainer/PromptInput/TextSizeMenu/index.jsx @@ -0,0 +1,124 @@ +import { useState, useRef, useEffect } from "react"; +import { TextT } from "@phosphor-icons/react"; +import { Tooltip } from "react-tooltip"; + +export default function TextSizeButton() { + const [showTextSizeMenu, setShowTextSizeMenu] = useState(false); + const buttonRef = useRef(null); + + return ( + <> + <div + ref={buttonRef} + id="text-size-btn" + data-tooltip-id="tooltip-text-size-btn" + data-tooltip-content="Change text size" + aria-label="Change text size" + onClick={() => setShowTextSizeMenu(!showTextSizeMenu)} + className={`relative flex justify-center items-center opacity-60 hover:opacity-100 cursor-pointer ${ + showTextSizeMenu ? "!opacity-100" : "" + }`} + > + <TextT + weight="fill" + className="w-6 h-6 pointer-events-none text-white" + /> + <Tooltip + id="tooltip-text-size-btn" + place="top" + delayShow={300} + className="tooltip !text-xs z-99" + /> + </div> + <TextSizeMenu + showing={showTextSizeMenu} + setShowing={setShowTextSizeMenu} + buttonRef={buttonRef} + /> + </> + ); +} + +function TextSizeMenu({ showing, setShowing, buttonRef }) { + const formRef = useRef(null); + const [selectedSize, setSelectedSize] = useState( + window.localStorage.getItem("anythingllm_text_size") || "normal" + ); + + useEffect(() => { + function listenForOutsideClick() { + if (!showing || !formRef.current) return false; + document.addEventListener("click", closeIfOutside); + } + listenForOutsideClick(); + }, [showing, formRef.current]); + + const closeIfOutside = ({ target }) => { + if (target.id === "text-size-btn") return; + const isOutside = !formRef?.current?.contains(target); + if (!isOutside) return; + setShowing(false); + }; + + const handleTextSizeChange = (size) => { + setSelectedSize(size); + window.localStorage.setItem("anythingllm_text_size", size); + window.dispatchEvent(new CustomEvent("textSizeChange", { detail: size })); + }; + + if (!buttonRef.current) return null; + + return ( + <div hidden={!showing}> + <div + ref={formRef} + className="absolute bottom-16 -ml-8 w-[140px] p-2 bg-zinc-800 rounded-lg shadow-md flex flex-col justify-center items-start gap-2 z-50" + > + <button + onClick={(e) => { + e.preventDefault(); + setShowing(false); + handleTextSizeChange("small"); + }} + className={`w-full hover:cursor-pointer px-2 py-1 rounded-md flex flex-col justify-start group ${ + selectedSize === "small" ? "bg-zinc-700" : "hover:bg-zinc-700" + }`} + > + <div className="w-full flex-col text-left flex pointer-events-none"> + <div className="text-white text-xs">Small</div> + </div> + </button> + + <button + onClick={(e) => { + e.preventDefault(); + setShowing(false); + handleTextSizeChange("normal"); + }} + className={`w-full hover:cursor-pointer px-2 py-1 rounded-md flex flex-col justify-start group ${ + selectedSize === "normal" ? "bg-zinc-700" : "hover:bg-zinc-700" + }`} + > + <div className="w-full flex-col text-left flex pointer-events-none"> + <div className="text-white text-sm">Normal</div> + </div> + </button> + + <button + onClick={(e) => { + e.preventDefault(); + setShowing(false); + handleTextSizeChange("large"); + }} + className={`w-full hover:cursor-pointer px-2 py-1 rounded-md flex flex-col justify-start group ${ + selectedSize === "large" ? "bg-zinc-700" : "hover:bg-zinc-700" + }`} + > + <div className="w-full flex-col text-left flex pointer-events-none"> + <div className="text-white text-[16px]">Large</div> + </div> + </button> + </div> + </div> + ); +} diff --git a/frontend/src/components/WorkspaceChat/ChatContainer/PromptInput/index.jsx b/frontend/src/components/WorkspaceChat/ChatContainer/PromptInput/index.jsx index cf460f3b08d0c099c360e2170aa5a85928dbf243..859f84174e3b7e9611f4f81ad65dd8f9e13b25d0 100644 --- a/frontend/src/components/WorkspaceChat/ChatContainer/PromptInput/index.jsx +++ b/frontend/src/components/WorkspaceChat/ChatContainer/PromptInput/index.jsx @@ -11,6 +11,7 @@ import AvailableAgentsButton, { AvailableAgents, useAvailableAgents, } from "./AgentMenu"; +import TextSizeButton from "./TextSizeMenu"; export default function PromptInput({ message, submit, @@ -137,6 +138,7 @@ export default function PromptInput({ showing={showAgents} setShowAgents={setShowAgents} /> + <TextSizeButton /> </div> </div> </div>