From ed68049bb50437ca2c86f6f629d91138dfac73c3 Mon Sep 17 00:00:00 2001 From: Mat Jordan Date: Tue, 17 Dec 2024 15:02:22 -0500 Subject: [PATCH] Refine interstitial design. --- components/Chat/Chat.tsx | 55 +++---------------- .../Chat/Response/Interstitial.styled.tsx | 42 ++++++++++++++ components/Chat/Response/Interstitial.tsx | 39 +++++++++++++ components/Chat/Response/Response.styled.tsx | 23 +------- components/Chat/Response/Response.tsx | 28 ++-------- components/Search/TextArea.styled.ts | 2 +- 6 files changed, 94 insertions(+), 95 deletions(-) create mode 100644 components/Chat/Response/Interstitial.styled.tsx create mode 100644 components/Chat/Response/Interstitial.tsx diff --git a/components/Chat/Chat.tsx b/components/Chat/Chat.tsx index 0826097f..96a2deab 100644 --- a/components/Chat/Chat.tsx +++ b/components/Chat/Chat.tsx @@ -1,21 +1,20 @@ +import { AI_DISCLAIMER, AI_SEARCH_UNSUBMITTED } from "@/lib/constants/common"; +import React, { useEffect, useState } from "react"; import { StyledResponseActions, StyledResponseDisclaimer, StyledUnsubmitted, } from "@/components/Chat/Response/Response.styled"; import { defaultState, useSearchState } from "@/context/search-context"; -import { AI_DISCLAIMER, AI_SEARCH_UNSUBMITTED } from "@/lib/constants/common"; -import React, { useEffect, useState } from "react"; +import Announcement from "@/components/Shared/Announcement"; +import { Button } from "@nulib/design-system"; import ChatFeedback from "@/components/Chat/Feedback/Feedback"; import ChatResponse from "@/components/Chat/Response/Response"; -import Announcement from "@/components/Shared/Announcement"; import Container from "@/components/Shared/Container"; +import { prepareQuestion } from "@/lib/chat-helpers"; import useChatSocket from "@/hooks/useChatSocket"; import useQueryParams from "@/hooks/useQueryParams"; -import { prepareQuestion } from "@/lib/chat-helpers"; -import { Work } from "@nulib/dcapi-types"; -import { Button } from "@nulib/design-system"; const Chat = ({ totalResults, @@ -38,10 +37,8 @@ const Chat = ({ searchState: { chat }, searchDispatch, } = useSearchState(); - const { question, answer, documents } = chat; + const { question } = chat; - const [sourceDocuments, setSourceDocuments] = useState([]); - const [streamedAnswer, setStreamedAnswer] = useState(""); const [isStreamingComplete, setIsStreamingComplete] = useState(false); useEffect(() => { @@ -56,14 +53,6 @@ const Chat = ({ useEffect(() => { if (!message) return; - // const updateSourceDocuments = () => { - // setSourceDocuments(message.source_documents!); - // }; - - // const updateStreamedAnswer = () => { - // setStreamedAnswer((prev) => prev + message.token); - // }; - // const updateChat = () => { // searchDispatch({ // chat: { @@ -76,35 +65,7 @@ const Chat = ({ // }); // }; - // if (message.source_documents) { - // updateSourceDocuments(); - // return; - // } - - // if (message.token) { - // updateStreamedAnswer(); - // return; - // } - - // if (message.end) { - // switch (message.end.reason) { - // case "length": - // setStreamingError("The response has hit the LLM token limit."); - // break; - // case "timeout": - // setStreamingError("The response has timed out."); - // break; - // case "eos_token": - // setStreamingError("This should never happen."); - // break; - // default: - // break; - // } - // } - - if (message?.type === "final_message") { - setIsStreamingComplete(true); - } + if (message.type === "final_message") setIsStreamingComplete(true); }, [message]); function handleNewQuestion() { @@ -120,8 +81,6 @@ const Chat = ({ chat: defaultState.chat, type: "updateChat", }); - setStreamedAnswer(""); - setSourceDocuments([]); } if (!searchTerm) diff --git a/components/Chat/Response/Interstitial.styled.tsx b/components/Chat/Response/Interstitial.styled.tsx new file mode 100644 index 00000000..6531af60 --- /dev/null +++ b/components/Chat/Response/Interstitial.styled.tsx @@ -0,0 +1,42 @@ +import { keyframes, styled } from "@/stitches.config"; + +const gradientAnimation = keyframes({ + to: { + backgroundSize: "500%", + backgroundPosition: "38.2%", + }, +}); + +const StyledInterstitial = styled("div", { + color: "$black", + margin: "$gr2 0", + borderRadius: "2rem", + fontFamily: "$northwesternSansBold", + fontSize: "$gr3", + display: "flex", + alignItems: "center", + gap: "$gr2", + + div: { + display: "flex", + width: "1.5rem", + height: "1.5rem", + alignItems: "center", + justifyContent: "center", + borderRadius: "50%", + background: + "linear-gradient(73deg, $purple120 0%, $purple 38.2%, $brightBlueB 61.8%)", + backgroundSize: "250%", + backgroundPosition: "61.8%", + animation: `${gradientAnimation} 3s infinite alternate`, + content: "", + + svg: { + fill: "$white", + width: "0.75rem", + height: "0.75rem", + }, + }, +}); + +export { StyledInterstitial }; diff --git a/components/Chat/Response/Interstitial.tsx b/components/Chat/Response/Interstitial.tsx new file mode 100644 index 00000000..7c2b6d42 --- /dev/null +++ b/components/Chat/Response/Interstitial.tsx @@ -0,0 +1,39 @@ +import { IconSearch } from "@/components/Shared/SVG/Icons"; +import { StyledInterstitial } from "./Interstitial.styled"; +import { ToolStartMessage } from "@/types/components/chat"; + +interface ResponseInterstitialProps { + message: ToolStartMessage["message"]; +} + +const ResponseInterstitial: React.FC = ({ + message, +}) => { + const { tool, input } = message; + let text = ""; + switch (tool) { + case "discover_fields": + text = "Discovering fields"; + break; + case "search": + text = `Searching for: ${input.query}`; + break; + case "aggregate": + console.log(`aggregate input`, input); + text = `Aggregating ${input.agg_field} by ${input.term_field} ${input.term}`; + break; + default: + console.warn("Unknown tool_start message", message); + } + + return ( + +
+ +
+ +
+ ); +}; + +export default ResponseInterstitial; diff --git a/components/Chat/Response/Response.styled.tsx b/components/Chat/Response/Response.styled.tsx index 0d3462a0..62100316 100644 --- a/components/Chat/Response/Response.styled.tsx +++ b/components/Chat/Response/Response.styled.tsx @@ -27,26 +27,6 @@ const StyledResponse = styled("section", { }, }); -const StyledInterstitial = styled("div", { - color: "$black", - padding: "$gr2 0", - fontFamily: "$northwesternSansBold", - fontSize: "$gr3", - display: "flex", - alignItems: "center", - gap: "$gr2", - margin: "0", - - div: { - display: "block", - width: "1.5rem", - height: "1.5rem", - borderRadius: "50%", - backgroundColor: "$brightBlueB", - content: "", - }, -}); - const StyledResponseAside = styled("aside", {}); const StyledResponseContent = styled("div", {}); @@ -96,7 +76,7 @@ const StyledImages = styled("div", { const StyledQuestion = styled("h3", { fontFamily: "$northwesternSansBold", fontWeight: "400", - fontSize: "$gr7", + fontSize: "$gr6", letterSpacing: "-0.012em", lineHeight: "1.35em", margin: "0", @@ -174,7 +154,6 @@ export { StyledResponseDisclaimer, StyledResponseWrapper, StyledImages, - StyledInterstitial, StyledQuestion, StyledResponseMarkdown, StyledUnsubmitted, diff --git a/components/Chat/Response/Response.tsx b/components/Chat/Response/Response.tsx index ef41e3bf..0637c0cb 100644 --- a/components/Chat/Response/Response.tsx +++ b/components/Chat/Response/Response.tsx @@ -1,15 +1,15 @@ import React, { useEffect, useState } from "react"; import { - StyledInterstitial, StyledQuestion, StyledResponse, StyledResponseWrapper, } from "./Response.styled"; -import ResponseImages from "@/components/Chat/Response/Images"; -import ResponseMarkdown from "@/components/Chat/Response/Markdown"; import BouncingLoader from "@/components/Shared/BouncingLoader"; import Container from "@/components/Shared/Container"; +import ResponseImages from "@/components/Chat/Response/Images"; +import ResponseInterstitial from "./Interstitial"; +import ResponseMarkdown from "@/components/Chat/Response/Markdown"; import { StreamingMessage } from "@/types/components/chat"; interface ChatResponseProps { @@ -50,31 +50,11 @@ const ChatResponse: React.FC = ({ } if (type === "tool_start") { - const { tool, input } = message.message; - let interstitialMessage = ""; - switch (tool) { - case "discover_fields": - interstitialMessage = "Discovering fields"; - break; - case "search": - interstitialMessage = `Searching for: ${input.query}`; - break; - case "aggregate": - console.log(`aggregate input`, input); - interstitialMessage = `Aggregating ${input.agg_field} by ${input.term_field} ${input.term}`; - break; - default: - console.warn("Unknown tool_start message", message); - } - // @ts-ignore setRenderedMessage((prev) => ( <> {prev} - -
- -
+ )); } diff --git a/components/Search/TextArea.styled.ts b/components/Search/TextArea.styled.ts index 2863bc8c..94aa4ba6 100644 --- a/components/Search/TextArea.styled.ts +++ b/components/Search/TextArea.styled.ts @@ -70,7 +70,7 @@ const StyledTextArea = styled("div", { "&::placeholder": { overflow: "hidden", - color: "$black80", + color: "$black50", textOverflow: "ellipsis", }, },