Skip to content
Snippets Groups Projects
Unverified Commit ff5d7d83 authored by Sean Hatfield's avatar Sean Hatfield Committed by GitHub
Browse files

[FEAT] Chat UI font size (#1172)

* WIP text font size change feature

* store text size settings in localstorage and improve styles of popup menu
parent 323c080b
No related branches found
No related tags found
No related merge requests found
......@@ -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)),
}}
......
......@@ -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
......
......@@ -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}
>
......
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>
);
}
......@@ -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>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment