@@ -28,7 +30,16 @@ export const Header = () => {
diff --git a/components/message.tsx b/components/message.tsx
index 264aa1f6..127e5fb1 100644
--- a/components/message.tsx
+++ b/components/message.tsx
@@ -7,9 +7,16 @@ import remarkGfm from 'remark-gfm'
import remarkMath from 'remark-math'
import rehypeKatex from 'rehype-katex'
import 'katex/dist/katex.min.css'
+import { useStreaming } from './streaming-context'
+import { useEffect } from 'react'
export function BotMessage({ content }: { content: StreamableValue
}) {
const [data, error, pending] = useStreamableValue(content)
+ const { setIsStreaming } = useStreaming()
+
+ useEffect(() => {
+ setIsStreaming(pending)
+ }, [pending, setIsStreaming])
// Currently, sometimes error occurs after finishing the stream.
if (error) return Error
diff --git a/components/streaming-context.tsx b/components/streaming-context.tsx
new file mode 100644
index 00000000..feb8536a
--- /dev/null
+++ b/components/streaming-context.tsx
@@ -0,0 +1,28 @@
+'use client'
+
+import { createContext, useContext, useState, ReactNode } from 'react'
+
+interface StreamingContextType {
+ isStreaming: boolean
+ setIsStreaming: (streaming: boolean) => void
+}
+
+const StreamingContext = createContext(undefined)
+
+export const useStreaming = () => {
+ const context = useContext(StreamingContext)
+ if (!context) {
+ throw new Error('useStreaming must be used within a StreamingProvider')
+ }
+ return context
+}
+
+export const StreamingProvider = ({ children }: { children: ReactNode }) => {
+ const [isStreaming, setIsStreaming] = useState(false)
+
+ return (
+
+ {children}
+
+ )
+}
diff --git a/tailwind.config.ts b/tailwind.config.ts
index 68c971ee..8b2af9e8 100644
--- a/tailwind.config.ts
+++ b/tailwind.config.ts
@@ -68,10 +68,15 @@ const config = {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: "0" },
},
+ "spin-ccw": {
+ from: { transform: "rotate(0deg)" },
+ to: { transform: "rotate(-360deg)" },
+ },
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
+ "spin-ccw": "spin-ccw 2s linear infinite",
},
fontFamily: {
sans: ["var(--font-sans)", ...fontFamily.sans],
From 5ab27d74230d3a59cd6b12dbadb7d4edabf9250b Mon Sep 17 00:00:00 2001
From: ngoiyaeric <115367894+ngoiyaeric@users.noreply.github.com>
Date: Thu, 13 Nov 2025 04:27:51 -0500
Subject: [PATCH 2/3] Fix SSR build error by providing default values in
useStreaming hook
---
components/streaming-context.tsx | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/components/streaming-context.tsx b/components/streaming-context.tsx
index feb8536a..4d900505 100644
--- a/components/streaming-context.tsx
+++ b/components/streaming-context.tsx
@@ -12,7 +12,8 @@ const StreamingContext = createContext(undefin
export const useStreaming = () => {
const context = useContext(StreamingContext)
if (!context) {
- throw new Error('useStreaming must be used within a StreamingProvider')
+ // Return default values if used outside provider (e.g., during SSR)
+ return { isStreaming: false, setIsStreaming: () => {} }
}
return context
}
From d33cd2fbea56934fa3eee4801ef21fc86f2e6775 Mon Sep 17 00:00:00 2001
From: ngoiyaeric <115367894+ngoiyaeric@users.noreply.github.com>
Date: Mon, 17 Nov 2025 06:22:33 -0500
Subject: [PATCH 3/3] Move StreamingProvider to root layout to ensure it wraps
Header component
---
app/layout.tsx | 13 ++++++++-----
components/chat.tsx | 17 ++++++-----------
2 files changed, 14 insertions(+), 16 deletions(-)
diff --git a/app/layout.tsx b/app/layout.tsx
index dd454b67..3f97ee89 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -16,6 +16,7 @@ import { CalendarToggleProvider } from '@/components/calendar-toggle-context'
import { MapLoadingProvider } from '@/components/map-loading-context';
import ConditionalLottie from '@/components/conditional-lottie';
import { MapProvider } from '@/components/map/map-context'
+import { StreamingProvider } from '@/components/streaming-context'
const fontSans = FontSans({
subsets: ['latin'],
@@ -60,8 +61,9 @@ export default function RootLayout({
-
+
-
-
-
+
+
+
+
diff --git a/components/chat.tsx b/components/chat.tsx
index 5a074042..2a775600 100644
--- a/components/chat.tsx
+++ b/components/chat.tsx
@@ -16,7 +16,6 @@ import { MapDataProvider, useMapData } from './map/map-data-context'; // Add thi
import { updateDrawingContext } from '@/lib/actions/chat'; // Import the server action
import dynamic from 'next/dynamic'
import { HeaderSearchButton } from './header-search-button'
-import { StreamingProvider } from './streaming-context'
type ChatProps = {
id?: string // This is the chatId
@@ -85,9 +84,8 @@ export function Chat({ id }: ChatProps) {
// Mobile layout
if (isMobile) {
return (
-
- {/* Add Provider */}
-
+ {/* Add Provider */}
+
{activeView ? : }
@@ -112,16 +110,14 @@ export function Chat({ id }: ChatProps) {
)}
-
-
+
);
}
// Desktop layout
return (
-
- {/* Add Provider */}
-
+ {/* Add Provider */}
+
{/* This is the new div for scrolling */}
@@ -149,7 +145,6 @@ export function Chat({ id }: ChatProps) {
{activeView ? : }
-
-
+
);
}