From 3836d707041d3a4c002e18676a97557524d68a5a Mon Sep 17 00:00:00 2001 From: sai karthik Date: Thu, 23 Jul 2026 17:07:17 +0530 Subject: [PATCH 01/31] feat(web): add mobile chat component system --- apps/web/package.json | 5 +- .../components/chat/assistant-identity.tsx | 31 +- .../web/src/components/chat/chat-composer.tsx | 106 ++---- .../src/components/chat/chat-conversation.tsx | 20 +- apps/web/src/components/chat/chat-header.tsx | 33 +- apps/web/src/components/chat/chat-message.tsx | 54 ++- apps/web/src/components/chat/chat-page.tsx | 10 +- .../chat/chat-thinking-response.tsx | 25 +- .../src/components/chat/chat-tool-call.tsx | 45 +-- apps/web/src/index.css | 51 --- apps/web/src/root.tsx | 10 +- apps/web/src/routes/design.mobile-chat.tsx | 66 ++++ apps/web/vite.config.ts | 6 +- bun.lock | 7 - packages/ui/src/components/mobile-chat.tsx | 334 ++++++++++++++++++ 15 files changed, 527 insertions(+), 276 deletions(-) create mode 100644 apps/web/src/routes/design.mobile-chat.tsx create mode 100644 packages/ui/src/components/mobile-chat.tsx diff --git a/apps/web/package.json b/apps/web/package.json index 526e014..0a57a70 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -7,7 +7,7 @@ "dev": "react-router dev", "dev:tailscale": "react-router dev --host 0.0.0.0", "start": "react-router-serve ./build/server/index.js", - "typecheck": "react-router typegen && tsc" + "check-types": "react-router typegen && tsc --noEmit" }, "dependencies": { "@code/auth": "workspace:*", @@ -39,7 +39,6 @@ "react-router-devtools": "^6.2.1", "tailwindcss": "catalog:", "typescript": "^6", - "vite": "^7.3.6", - "vite-tsconfig-paths": "^6.1.1" + "vite": "^7.3.6" } } diff --git a/apps/web/src/components/chat/assistant-identity.tsx b/apps/web/src/components/chat/assistant-identity.tsx index 05f6314..47038ef 100644 --- a/apps/web/src/components/chat/assistant-identity.tsx +++ b/apps/web/src/components/chat/assistant-identity.tsx @@ -1,5 +1,4 @@ -import { MessageHeader } from "@code/ui/components/message"; -import { Sparkles } from "lucide-react"; +import { MobileChatAssistantLabel } from "@code/ui/components/mobile-chat"; import type { AssistantResponseState } from "@/lib/chat/types"; @@ -8,20 +7,18 @@ interface AssistantIdentityProps { } export const AssistantIdentity = ({ state }: AssistantIdentityProps) => ( - - - - - Zopu - {state && ( - - - {state === "thinking" ? "Thinking" : "Writing"} - - )} - + ) : undefined + } + /> ); diff --git a/apps/web/src/components/chat/chat-composer.tsx b/apps/web/src/components/chat/chat-composer.tsx index a68544e..1b2466a 100644 --- a/apps/web/src/components/chat/chat-composer.tsx +++ b/apps/web/src/components/chat/chat-composer.tsx @@ -1,10 +1,5 @@ -import { - InputGroup, - InputGroupAddon, - InputGroupButton, - InputGroupTextarea, -} from "@code/ui/components/input-group"; -import { CircleAlert, LoaderCircle, Send } from "lucide-react"; +import { MobileChatComposer } from "@code/ui/components/mobile-chat"; +import { LoaderCircle } from "lucide-react"; import type { ReactNode } from "react"; import { useChatComposer } from "@/hooks/chat/use-chat-composer"; @@ -14,90 +9,31 @@ export const ChatComposer = ({ error, onSend, status }: ChatComposerProps) => { const busy = status === "submitted" || status === "streaming"; const composer = useChatComposer({ busy, onSend }); - let statusContent: ReactNode = ( - - Enter to send · Shift + Enter for a new line - - ); + let statusMessage: ReactNode; if (busy) { - statusContent = ( - <> - + statusMessage = ( + + Zopu is responding - - ); - } - if (error) { - statusContent = ( - - - {error.message || "Message failed to send"} ); } return ( -
-
- - - - - {busy ? ( - - ) : ( - - )} - - - -
- {composer.isFocused || busy || error ? ( - {statusContent} - ) : ( - Zopu can make mistakes. Check important information. - )} -
-
-
+ ); }; diff --git a/apps/web/src/components/chat/chat-conversation.tsx b/apps/web/src/components/chat/chat-conversation.tsx index 686e675..9763572 100644 --- a/apps/web/src/components/chat/chat-conversation.tsx +++ b/apps/web/src/components/chat/chat-conversation.tsx @@ -9,7 +9,7 @@ import { } from "@code/ui/components/empty"; import { MessageGroup } from "@code/ui/components/message"; import { MessageScrollerItem } from "@code/ui/components/message-scroller"; -import { Sparkles } from "lucide-react"; +import { MobileChatMark } from "@code/ui/components/mobile-chat"; import { SUGGESTIONS } from "@/lib/chat/constants"; import type { ChatConversationProps } from "@/lib/chat/types"; @@ -25,23 +25,23 @@ export const ChatConversation = ({ }: ChatConversationProps) => { if (historyReady && messages.length === 0) { return ( - - - + + + - - + + What can I help with? - + Think, write, plan, or explore an idea with Zopu. - + {SUGGESTIONS.map(([title, prompt]) => (