From 6668361f0584e9d86c1c238efb3ec107ec534baf Mon Sep 17 00:00:00 2001 From: Avraham Sakal Date: Sun, 14 Sep 2025 16:17:01 -0400 Subject: [PATCH] UI overhaul: fonts, colors, scrollable message boxes, animated text generation status updates --- layouts/LayoutDefault.tsx | 16 +++++-- layouts/theme.ts | 12 +++++ pages/chat/@id/+Page.tsx | 92 +++++++++++++++++++++++++++++++++------ 3 files changed, 104 insertions(+), 16 deletions(-) diff --git a/layouts/LayoutDefault.tsx b/layouts/LayoutDefault.tsx index cb5b84b..b1d08b2 100644 --- a/layouts/LayoutDefault.tsx +++ b/layouts/LayoutDefault.tsx @@ -100,7 +100,7 @@ export default function LayoutDefault({ - + {" "} - Token-Efficient Context Engineering + + Token-Efficient Context Engineering + diff --git a/layouts/theme.ts b/layouts/theme.ts index 8f25715..57f48d2 100644 --- a/layouts/theme.ts +++ b/layouts/theme.ts @@ -110,6 +110,18 @@ const theme: MantineThemeOverride = createTheme({ "3xl": "2.25rem", "4xl": "3rem", }, + lineHeights: { + xs: "1.25rem", + sm: "1.375rem", + md: "1.5rem", + lg: "1.75rem", + xl: "2rem", + "2xl": "2.25rem", + "3xl": "2.625rem", + "4xl": "3rem", + "5xl": "3.75rem", + "6xl": "4.5rem", + }, }); export default theme; diff --git a/pages/chat/@id/+Page.tsx b/pages/chat/@id/+Page.tsx index 2188c4b..91d9ad5 100644 --- a/pages/chat/@id/+Page.tsx +++ b/pages/chat/@id/+Page.tsx @@ -5,12 +5,16 @@ import { HoverCard, JsonInput, List, + ScrollArea, Stack, Tabs, + Text, Textarea, + TextInput, + Transition, useMantineTheme, } from "@mantine/core"; -import { useEffect, useState } from "react"; +import { memo, useEffect, useState } from "react"; import { defaultParameters, defaultSystemPrompt, @@ -23,6 +27,7 @@ import type { CommittedMessage, DraftMessage, OtherParameters, + SendMessageStatus, } from "../../../types"; import Markdown from "react-markdown"; import { @@ -351,6 +356,8 @@ export default function ChatPage() { const setSendMessageStatus = useStore((state) => state.setSendMessageStatus); const setIsSendingMessage = useStore((state) => state.setIsSendingMessage); + const theme = useMantineTheme(); + // Function to send message using subscription const sendSubscriptionMessage = async ({ conversationId, @@ -489,11 +496,11 @@ export default function ChatPage() { } return ( - <> -
- Conversation #{conversationId} - - + + { // setConversationTitle(e.target.value); @@ -504,10 +511,27 @@ export default function ChatPage() { title: e.target.value, }); }} + variant="unstyled" + styles={{ + input: { + // backgroundColor: "transparent", + // border: "none", + // padding: 0, + // margin: 0, + fontFamily: theme.headings.fontFamily, + fontSize: theme.fontSizes.lg, + lineHeight: theme.lineHeights["4xl"], + }, + wrapper: { + marginTop: 0, + }, + }} /> {isSendingMessage && } - {sendMessageStatus && {sendMessageStatus.message}} -
+ {sendMessageStatus && ( + + )} + Message @@ -690,7 +714,7 @@ export default function ChatPage() { - + ); } @@ -792,15 +816,16 @@ function Messages() { position={message.role === "user" ? "left" : "right"} > - {message.parts @@ -808,7 +833,7 @@ function Messages() { .map((p) => p.text) .join("\n")} - + @@ -840,3 +865,44 @@ function Messages() { ); } + +const StatusMessage = memo( + ({ sendMessageStatus }: { sendMessageStatus: SendMessageStatus | null }) => { + const [displayMessage, setDisplayMessage] = useState(sendMessageStatus); + const [isVisible, setIsVisible] = useState(sendMessageStatus !== null); + + useEffect(() => { + if (sendMessageStatus === null) { + setIsVisible(false); + setTimeout(() => setDisplayMessage(null), 250); + } else if (displayMessage === null) { + setDisplayMessage(sendMessageStatus); + setIsVisible(true); + } else if (displayMessage.message !== sendMessageStatus.message) { + setIsVisible(false); + setTimeout(() => { + setDisplayMessage(sendMessageStatus); + setIsVisible(true); + }, 250); + } + }, [sendMessageStatus, displayMessage]); + + return ( +
+ {/* This is a hack to make this component take up the space it would take up once the transition is complete. Useful for when this component is in a flexbox with a particular alignment/justification, which we want to be calculated against its eventual size. */} + {displayMessage?.message} + + {(styles) => ( + + {displayMessage?.message} + + )} + +
+ ); + } +);