From 39525b1a41fc7f1477666713ca47b32e9a5c84cd Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 29 Sep 2025 13:42:26 +0000 Subject: [PATCH 1/2] feat: Make example prompts interactive and conditionally visible This commit implements the following changes: 1. The example prompts on the empty chat screen are now hidden by default and only appear when the user focuses on the chat input. 2. Clicking on an example prompt now submits it as a query to the AI, and the response is displayed in the chat. These changes were accomplished by: - Adding an `onFocus` handler to the `ChatPanel` component to detect when the user interacts with the input field. - Introducing an `isInputFocused` state in the `Chat` component to control the visibility of the example prompts in the `EmptyScreen` component. - Updating the `submitMessage` function in the `Chat` component to use the `submit` action from `ai/rsc`, which handles the entire chat flow. --- components/chat-panel.tsx | 9 ++++- components/chat.tsx | 69 +++++++++++++++++++++++++++++-------- components/empty-screen.tsx | 43 ++++++++++++----------- 3 files changed, 86 insertions(+), 35 deletions(-) diff --git a/components/chat-panel.tsx b/components/chat-panel.tsx index c5268ead..075636b1 100644 --- a/components/chat-panel.tsx +++ b/components/chat-panel.tsx @@ -15,9 +15,15 @@ interface ChatPanelProps { messages: UIState input: string setInput: (value: string) => void + onFocus: () => void } -export function ChatPanel({ messages, input, setInput }: ChatPanelProps) { +export function ChatPanel({ + messages, + input, + setInput, + onFocus +}: ChatPanelProps) { const [, setMessages] = useUIState() const { submit, clearChat } = useActions() // Removed mcp instance as it's no longer passed to submit @@ -121,6 +127,7 @@ export function ChatPanel({ messages, input, setInput }: ChatPanelProps) { onChange={e => { setInput(e.target.value) }} + onFocus={onFocus} onKeyDown={e => { if ( e.key === 'Enter' && diff --git a/components/chat.tsx b/components/chat.tsx index 59c4d914..2d4d53af 100644 --- a/components/chat.tsx +++ b/components/chat.tsx @@ -6,9 +6,11 @@ import { ChatPanel } from './chat-panel' import { ChatMessages } from './chat-messages' import { EmptyScreen } from './empty-screen' import { Mapbox } from './map/mapbox-map' -import { useUIState, useAIState } from 'ai/rsc' +import { useUIState, useAIState, useActions } from 'ai/rsc' +import { nanoid } from 'nanoid' +import { UserMessage } from './user-message' import MobileIconsBar from './mobile-icons-bar' -import { useProfileToggle, ProfileToggleEnum } from "@/components/profile-toggle-context"; +import { useProfileToggle, ProfileToggleEnum } from '@/components/profile-toggle-context' import SettingsView from "@/components/settings/settings-view"; import { MapDataProvider, useMapData } from './map/map-data-context'; // Add this and useMapData import { updateDrawingContext } from '@/lib/actions/chat'; // Import the server action @@ -20,12 +22,14 @@ type ChatProps = { export function Chat({ id }: ChatProps) { const router = useRouter() const path = usePathname() - const [messages] = useUIState() + const [messages, setMessages] = useUIState() const [aiState] = useAIState() + const { submit } = useActions() const [isMobile, setIsMobile] = useState(false) - const { activeView } = useProfileToggle(); + const { activeView } = useProfileToggle() const [input, setInput] = useState('') const [showEmptyScreen, setShowEmptyScreen] = useState(false) + const [isInputFocused, setIsInputFocused] = useState(false) useEffect(() => { setShowEmptyScreen(messages.length === 0) @@ -83,13 +87,30 @@ export function Chat({ id }: ChatProps) {
- + setIsInputFocused(true)} + />
{showEmptyScreen ? ( { - setInput(message) + isInputFocused={isInputFocused} + submitMessage={async (message: string) => { + setMessages(currentMessages => [ + ...currentMessages, + { + id: nanoid(), + component: + } + ]) + const responseMessage = await submit(message) + setMessages(currentMessages => [ + ...currentMessages, + responseMessage as any + ]) }} /> ) : ( @@ -98,20 +119,40 @@ export function Chat({ id }: ChatProps) {
- ); + ) } - + // Desktop layout return ( - {/* Add Provider */} + + {' '} + {/* Add Provider */}
{/* This is the new div for scrolling */}
- + setIsInputFocused(true)} + /> {showEmptyScreen ? ( { - setInput(message) + isInputFocused={isInputFocused} + submitMessage={async (message: string) => { + setMessages(currentMessages => [ + ...currentMessages, + { + id: nanoid(), + component: + } + ]) + + const responseMessage = await submit(message) + setMessages(currentMessages => [ + ...currentMessages, + responseMessage as any + ]) }} /> ) : ( @@ -126,5 +167,5 @@ export function Chat({ id }: ChatProps) {
- ); + ) } diff --git a/components/empty-screen.tsx b/components/empty-screen.tsx index 2c0f63e4..7c96104f 100644 --- a/components/empty-screen.tsx +++ b/components/empty-screen.tsx @@ -27,33 +27,36 @@ const exampleMessages = [ export function EmptyScreen({ submitMessage, className, + isInputFocused }: { - submitMessage: (message: string) => void; - className?: string; + submitMessage: (message: string) => void + className?: string + isInputFocused: boolean }) { return (
- {exampleMessages.map((item) => { - const Icon = item.icon; - return ( - - ); - })} + {isInputFocused && + exampleMessages.map(item => { + const Icon = item.icon + return ( + + ) + })}
- ); + ) } From ed628eb84e61e84622e2a54db534acf6fea8de38 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 29 Sep 2025 13:51:07 +0000 Subject: [PATCH 2/2] feat: Make example prompts interactive and conditionally visible This commit implements the following changes: 1. The example prompts on the empty chat screen are now hidden by default and only appear when the user focuses on the chat input. 2. Clicking on an example prompt now submits it as a query to the AI, and the response is displayed in the chat. These changes were accomplished by: - Adding an `onFocus` handler to the `ChatPanel` component to detect when the user interacts with the input field. - Introducing an `isInputFocused` state in the `Chat` component to control the visibility of the example prompts in the `EmptyScreen` component. - Updating the `submitMessage` function in the `Chat` component to use the `submit` action from `ai/rsc`, which handles the entire chat flow. - Fixing a TypeScript error by explicitly typing the `currentMessages` parameter in the `setMessages` function. --- components/chat.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/components/chat.tsx b/components/chat.tsx index 2d4d53af..9fba42cf 100644 --- a/components/chat.tsx +++ b/components/chat.tsx @@ -9,6 +9,7 @@ import { Mapbox } from './map/mapbox-map' import { useUIState, useAIState, useActions } from 'ai/rsc' import { nanoid } from 'nanoid' import { UserMessage } from './user-message' +import { UIState } from '@/app/actions' import MobileIconsBar from './mobile-icons-bar' import { useProfileToggle, ProfileToggleEnum } from '@/components/profile-toggle-context' import SettingsView from "@/components/settings/settings-view"; @@ -99,7 +100,7 @@ export function Chat({ id }: ChatProps) { { - setMessages(currentMessages => [ + setMessages((currentMessages: UIState) => [ ...currentMessages, { id: nanoid(), @@ -107,7 +108,7 @@ export function Chat({ id }: ChatProps) { } ]) const responseMessage = await submit(message) - setMessages(currentMessages => [ + setMessages((currentMessages: UIState) => [ ...currentMessages, responseMessage as any ]) @@ -140,7 +141,7 @@ export function Chat({ id }: ChatProps) { { - setMessages(currentMessages => [ + setMessages((currentMessages: UIState) => [ ...currentMessages, { id: nanoid(), @@ -149,7 +150,7 @@ export function Chat({ id }: ChatProps) { ]) const responseMessage = await submit(message) - setMessages(currentMessages => [ + setMessages((currentMessages: UIState) => [ ...currentMessages, responseMessage as any ])