From dc47ba065c0c2adc5d394c64973e81ea6d7da3f4 Mon Sep 17 00:00:00 2001 From: Debanjum Singh Solanky Date: Wed, 31 Jul 2024 22:27:15 +0530 Subject: [PATCH] Use Turnstyle UX pattern to group Khoj chats into conversation turns A turn is defined as a single back and forth between the user and AI. A typical user - agent interaction is more strongly coupled into a request, response pair than a typical chat message interaction between humans. Turnstyle UX emphasis this natural coupling of the request, response pairs by grouping a conversation turn more strongly together than the older, more typical chat bubble UX. Turnstyle UX renders each user's query and AI's response into a section heading, section content respectively for cleaner, more natural demarcation of a single interaction --- .../components/chatHistory/chatHistory.tsx | 4 +- .../chatMessage/chatMessage.module.css | 25 ++-- .../components/chatMessage/chatMessage.tsx | 112 ++++++++++-------- 3 files changed, 78 insertions(+), 63 deletions(-) diff --git a/src/interface/web/app/components/chatHistory/chatHistory.tsx b/src/interface/web/app/components/chatHistory/chatHistory.tsx index 2505dbf7..bc4075b6 100644 --- a/src/interface/web/app/components/chatHistory/chatHistory.tsx +++ b/src/interface/web/app/components/chatHistory/chatHistory.tsx @@ -265,7 +265,7 @@ export default function ChatHistory(props: ChatHistoryProps) { chatMessage={chatMessage} customClassName='fullHistory' borderLeftColor={`${data?.agent.color}-500`} - isLastMessage={index === data.chat.length - 1} + isLastMessage={index === data.chat.length - 2} /> ))} { @@ -288,6 +288,7 @@ export default function ChatHistory(props: ChatHistoryProps) { } customClassName='fullHistory' borderLeftColor={`${data?.agent.color}-500`} + isLastMessage={true} /> { message.trainOfThought && @@ -313,7 +314,6 @@ export default function ChatHistory(props: ChatHistoryProps) { } customClassName='fullHistory' borderLeftColor={`${data?.agent.color}-500`} - isLastMessage={true} /> ) diff --git a/src/interface/web/app/components/chatMessage/chatMessage.module.css b/src/interface/web/app/components/chatMessage/chatMessage.module.css index 809acc2e..a00bdd61 100644 --- a/src/interface/web/app/components/chatMessage/chatMessage.module.css +++ b/src/interface/web/app/components/chatMessage/chatMessage.module.css @@ -1,14 +1,22 @@ div.chatMessageContainer { display: flex; flex-direction: column; - margin: 12px; border-radius: 16px; +} +div.chatMessageContainer.khoj { + margin: 0; padding: 8px 16px 0 16px; + box-shadow: 0 4px 10px var(--box-shadow-color); + border-top: transparent; +} +div.chatMessageContainer.you { + margin-top: 12px; + padding-top: 16px; + box-shadow: none; + border-top: transparent; } div.chatMessageWrapper { - padding-left: 1rem; - padding-bottom: 1rem; max-width: 80vw; } div.chatMessageWrapper p:not(:last-child) { @@ -25,23 +33,22 @@ div.youfullHistory { } div.chatMessageContainer.youfullHistory { - padding-left: 0px; + padding-left: 16px; } div.you { - background-color: hsla(var(--secondary)); - align-self: flex-end; - border-radius: 16px; + background-color: transparent; + align-self: flex-start; } div.khoj { background-color: transparent; color: hsl(var(--accent-foreground)); align-self: flex-start; + padding-left: 1rem; } div.khojChatMessage { - padding-top: 8px; padding-left: 16px; } @@ -64,8 +71,6 @@ div.author { } div.chatFooter { - display: flex; - justify-content: space-between; min-height: 28px; } diff --git a/src/interface/web/app/components/chatMessage/chatMessage.tsx b/src/interface/web/app/components/chatMessage/chatMessage.tsx index 71a5b29e..40c86abd 100644 --- a/src/interface/web/app/components/chatMessage/chatMessage.tsx +++ b/src/interface/web/app/components/chatMessage/chatMessage.tsx @@ -10,7 +10,7 @@ import 'katex/dist/katex.min.css'; import { TeaserReferencesSection, constructAllReferences } from '../referencePanel/referencePanel'; -import { ThumbsUp, ThumbsDown, Copy, Brain, Cloud, Folder, Book, Aperture, SpeakerHigh, MagnifyingGlass, Pause, Palette } from '@phosphor-icons/react'; +import { ThumbsUp, ThumbsDown, Copy, Brain, Cloud, Folder, Book, Aperture, SpeakerHigh, MagnifyingGlass, Pause, Palette, Clock } from '@phosphor-icons/react'; import DOMPurify from 'dompurify'; import { InlineLoading } from '../loading/loading'; @@ -331,8 +331,12 @@ export default function ChatMessage(props: ChatMessageProps) { } function chatMessageWrapperClasses(chatMessage: SingleChatMessage) { - let classes = [styles.chatMessageWrapper]; - classes.push(styles[chatMessage.by]); + let classes = [styles.chatMessageWrapper, styles[chatMessage.by]]; + if (chatMessage.by === "you") { + let fontClass = chatMessage.message.length > 100 ? "text-md" : "text-xl"; + classes.push(fontClass); + } + if (chatMessage.by === "khoj") { classes.push(`border-l-4 border-opacity-50 ${"border-l-" + props.borderLeftColor || "border-l-orange-400"}`); } @@ -429,58 +433,64 @@ export default function ChatMessage(props: ChatMessageProps) { notesReferenceCardData={allReferences.notesReferenceCardData} onlineReferenceCardData={allReferences.onlineReferenceCardData} /> -
{ - (isHovering || props.isMobileWidth || props.isLastMessage || isPlaying) && + props.chatMessage.by === "you" && ( - <> -
- {renderTimeStamp(props.chatMessage.created)} -
-
- { - (props.chatMessage.by === "khoj") && - ( - isPlaying ? - ( - interrupted ? - - : - ) - : - ) - } - - { - (props.chatMessage.by === "khoj") && - ( - props.chatMessage.intent ? - - : - ) - } -
- +
+ { + (isHovering || props.isMobileWidth || props.isLastMessage || isPlaying) && ( +
+ + {renderTimeStamp(props.chatMessage.created)} +
+ ) + } +
+ ) || props.chatMessage.by === "khoj" && + ( +
+ { + (isHovering || props.isMobileWidth || props.isLastMessage || isPlaying) && + ( +
+ { + isPlaying ? + ( + interrupted ? + + : + ) + : + } + + { + props.chatMessage.intent ? + + : + } +
+ ) + } +
) } -
) }