Skip to content

Commit 007c7f8

Browse files
committed
Update the styles to match Array app
1 parent 43f5aa8 commit 007c7f8

File tree

13 files changed

+379
-158
lines changed

13 files changed

+379
-158
lines changed

apps/mobile/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,14 @@
3030
"expo-system-ui": "~6.0.9",
3131
"expo-web-browser": "^15.0.10",
3232
"nativewind": "^4.2.1",
33+
"phosphor-react-native": "^3.0.2",
3334
"react": "19.1.0",
3435
"react-native": "0.81.5",
3536
"react-native-keyboard-controller": "1.18.5",
3637
"react-native-reanimated": "~4.1.1",
3738
"react-native-safe-area-context": "~5.6.2",
3839
"react-native-screens": "~4.16.0",
40+
"react-native-svg": "^15.15.1",
3941
"react-native-webview": "^13.13.5",
4042
"zustand": "^4.5.7"
4143
},

apps/mobile/src/app/chat.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ export default function ChatScreen() {
5252
options={{
5353
headerShown: true,
5454
headerTitle: "Chat",
55-
headerBackTitle: "Back",
5655
headerStyle: { backgroundColor: "#09090b" },
5756
headerTintColor: "#fff",
5857
headerTitleStyle: {

apps/mobile/src/app/conversation/[id].tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ export default function ConversationDetailScreen() {
7979
options={{
8080
headerShown: true,
8181
headerTitle: "Error",
82-
headerBackTitle: "Back",
8382
headerStyle: { backgroundColor: "#09090b" },
8483
headerTintColor: "#fff",
8584
}}
@@ -104,7 +103,7 @@ export default function ConversationDetailScreen() {
104103
options={{
105104
headerShown: true,
106105
headerTitle: "Loading...",
107-
headerBackTitle: "Back",
106+
headerBackTitle: "",
108107
headerStyle: { backgroundColor: "#09090b" },
109108
headerTintColor: "#fff",
110109
}}
@@ -125,7 +124,7 @@ export default function ConversationDetailScreen() {
125124
options={{
126125
headerShown: true,
127126
headerTitle: conversation?.title || "Conversation",
128-
headerBackTitle: "Back",
127+
headerBackTitle: "",
129128
headerStyle: { backgroundColor: "#09090b" },
130129
headerTintColor: "#fff",
131130
headerTitleStyle: {

apps/mobile/src/components/AIMessage.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ export function AIMessage({
1616
toolCalls,
1717
}: AIMessageProps) {
1818
return (
19-
<View className="items-start py-2">
19+
<View className="py-2">
2020
{toolCalls && toolCalls.length > 0 && (
21-
<View className="mb-1 w-full">
21+
<View className="mb-1">
2222
{toolCalls.map((tc) => (
2323
<ToolCallMessage
2424
key={tc.id}
@@ -30,16 +30,16 @@ export function AIMessage({
3030
</View>
3131
)}
3232
{(content || isLoading) && (
33-
<View className="mx-4 max-w-[85%] rounded-2xl rounded-bl-md bg-dark-surface px-4 py-3">
33+
<View className="max-w-[95%] px-4 py-1">
3434
{isLoading && !content ? (
3535
<View className="flex-row items-center gap-2">
36-
<ActivityIndicator size="small" color="#a3a3a3" />
37-
<Text className="text-base text-dark-text-muted italic">
38-
{thinkingText || "Thinking..."}
36+
<ActivityIndicator size="small" color="#f1a82c" />
37+
<Text className="font-mono text-[13px] text-neutral-400 italic">
38+
{thinkingText || "Generating..."}
3939
</Text>
4040
</View>
4141
) : (
42-
<Text className="text-base text-dark-text leading-6">
42+
<Text className="font-mono text-[13px] text-neutral-200 leading-5">
4343
{content}
4444
</Text>
4545
)}

apps/mobile/src/components/FailureMessage.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ interface FailureMessageProps {
66

77
export function FailureMessage({ content }: FailureMessageProps) {
88
return (
9-
<View className="items-start px-4 py-2">
10-
<View className="max-w-[85%] rounded-2xl rounded-bl-md bg-red-900/30 px-4 py-3">
11-
<Text className="text-base text-red-300 leading-6">
9+
<View className="px-4 py-2">
10+
<View className="max-w-[95%] bg-red-500/15 px-3 py-2">
11+
<Text className="font-mono text-[13px] text-red-300 leading-5">
1212
{content || "Something went wrong. Please try again."}
1313
</Text>
1414
</View>

apps/mobile/src/components/HumanMessage.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ interface HumanMessageProps {
66

77
export function HumanMessage({ content }: HumanMessageProps) {
88
return (
9-
<View className="items-end px-4 py-2">
10-
<View className="max-w-[85%] rounded-2xl rounded-br-md bg-orange-500 px-4 py-3">
11-
<Text className="text-base text-white leading-6">{content}</Text>
9+
<View className="px-4 py-2">
10+
<View className="mt-3 max-w-[95%] bg-amber-500/20 px-3 py-2">
11+
<Text className="font-mono text-[13px] text-amber-100 leading-5">
12+
{content}
13+
</Text>
1214
</View>
1315
</View>
1416
);

apps/mobile/src/components/MessagesList.tsx

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ function MessageItem({ item }: { item: ThreadMessage }) {
4747
}
4848

4949
if (isArtifactMessage(item) && isVisualizationArtifactContent(item.content)) {
50-
// TODO: Handle artifact messages (visualizations)
5150
return <VisualizationArtifact message={item} content={item.content} />;
5251
}
5352

@@ -61,14 +60,12 @@ export function MessagesList({
6160
}: MessagesListProps) {
6261
const flatListRef = useRef<FlatList>(null);
6362

64-
// Scroll to bottom when new messages arrive
6563
useEffect(() => {
6664
if (messages.length > 0 && flatListRef.current) {
6765
flatListRef.current.scrollToOffset({ offset: 0, animated: true });
6866
}
6967
}, [messages.length]);
7068

71-
// Reverse messages for inverted FlatList
7269
const reversedMessages = [...messages].reverse();
7370

7471
return (
@@ -87,10 +84,10 @@ export function MessagesList({
8784
className="flex-1 items-center justify-center px-8"
8885
style={{ transform: [{ scaleY: -1 }] }}
8986
>
90-
<Text className="mb-2 text-center font-semibold text-dark-text text-xl">
87+
<Text className="mb-2 text-center font-mono text-lg text-neutral-200">
9188
Start a conversation
9289
</Text>
93-
<Text className="text-center text-base text-dark-text-muted">
90+
<Text className="text-center font-mono text-[13px] text-neutral-500">
9491
Ask Max anything about your product data
9592
</Text>
9693
</View>
@@ -100,10 +97,10 @@ export function MessagesList({
10097
messages.length > 0 &&
10198
messages[messages.length - 1]?.status !== "loading" ? (
10299
<View className="items-start px-4 py-2">
103-
<View className="flex-row items-center gap-2 rounded-2xl rounded-bl-md bg-dark-surface px-4 py-3">
104-
<ActivityIndicator size="small" color="#a3a3a3" />
105-
<Text className="text-base text-dark-text-muted italic">
106-
Thinking...
100+
<View className="flex-row items-center gap-2 py-1">
101+
<ActivityIndicator size="small" color="#f1a82c" />
102+
<Text className="font-mono text-[13px] italic text-neutral-400">
103+
Generating...
107104
</Text>
108105
</View>
109106
</View>

apps/mobile/src/components/ToolCallMessage.tsx

Lines changed: 112 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,160 @@
1+
import {
2+
ArrowsClockwise,
3+
Brain,
4+
CaretRight,
5+
FileText,
6+
Globe,
7+
type IconProps,
8+
MagnifyingGlass,
9+
PencilSimple,
10+
Terminal,
11+
Trash,
12+
Wrench,
13+
} from "phosphor-react-native";
114
import { useState } from "react";
215
import { ActivityIndicator, Pressable, Text, View } from "react-native";
316

417
type ToolStatus = "pending" | "running" | "completed" | "error";
18+
type ToolKind =
19+
| "read"
20+
| "edit"
21+
| "delete"
22+
| "move"
23+
| "search"
24+
| "execute"
25+
| "think"
26+
| "fetch"
27+
| "switch_mode"
28+
| "other";
29+
30+
type PhosphorIcon = React.ComponentType<IconProps>;
31+
32+
const kindIcons: Record<ToolKind, PhosphorIcon> = {
33+
read: FileText,
34+
edit: PencilSimple,
35+
delete: Trash,
36+
move: FileText,
37+
search: MagnifyingGlass,
38+
execute: Terminal,
39+
think: Brain,
40+
fetch: Globe,
41+
switch_mode: ArrowsClockwise,
42+
other: Wrench,
43+
};
544

645
interface ToolCallMessageProps {
746
toolName: string;
47+
kind?: ToolKind;
848
status: ToolStatus;
949
args?: Record<string, unknown>;
1050
result?: unknown;
1151
}
1252

13-
// Icon components using text/emoji (simple approach for RN)
14-
function ToolIcon({ status }: { status: ToolStatus }) {
15-
if (status === "pending" || status === "running") {
16-
return <ActivityIndicator size={12} color="#a3a3a3" />;
53+
function formatToolTitle(
54+
toolName: string,
55+
args?: Record<string, unknown>,
56+
): string {
57+
if (!args) return toolName;
58+
59+
// Format common tool patterns like the desktop app
60+
if (toolName.toLowerCase() === "grep" && args.pattern) {
61+
return `grep "${args.pattern}"`;
62+
}
63+
if (toolName.toLowerCase() === "read_file" && args.target_file) {
64+
return "Read File";
65+
}
66+
if (toolName.toLowerCase() === "write" && args.file_path) {
67+
return "Write File";
68+
}
69+
if (toolName.toLowerCase() === "search_replace") {
70+
return "Search Replace";
1771
}
18-
return <Text className="text-dark-text-muted text-xs">⚙️</Text>;
19-
}
2072

21-
function CaretIcon({ isOpen }: { isOpen: boolean }) {
22-
return (
23-
<Text
24-
className="text-dark-text-muted text-xs"
25-
style={{ transform: [{ rotate: isOpen ? "90deg" : "0deg" }] }}
26-
>
27-
28-
</Text>
29-
);
73+
return toolName;
3074
}
3175

3276
export function ToolCallMessage({
3377
toolName,
78+
kind,
3479
status,
3580
args,
3681
result,
3782
}: ToolCallMessageProps) {
3883
const [isOpen, setIsOpen] = useState(false);
3984

85+
const isLoading = status === "pending" || status === "running";
4086
const isFailed = status === "error";
4187
const hasDetails = args || result !== undefined;
88+
const displayTitle = formatToolTitle(toolName, args);
89+
const KindIcon = kind ? kindIcons[kind] : Wrench;
4290

4391
return (
44-
<View className="px-4 py-1">
92+
<View className="px-4 py-0.5">
4593
<Pressable
4694
onPress={() => hasDetails && setIsOpen(!isOpen)}
47-
className="flex-row items-center gap-2 rounded-lg bg-dark-surface/50 px-3 py-2"
48-
style={{ opacity: hasDetails ? 1 : 0.7 }}
95+
className="flex-row items-center gap-2"
96+
disabled={!hasDetails}
4997
>
50-
<CaretIcon isOpen={isOpen} />
51-
<ToolIcon status={status} />
52-
<Text className="font-mono text-dark-text-muted text-sm">
53-
{toolName}
98+
{/* Caret */}
99+
<CaretRight
100+
size={12}
101+
color="#6e6e6b"
102+
style={{ transform: [{ rotate: isOpen ? "90deg" : "0deg" }] }}
103+
/>
104+
105+
{/* Status indicator */}
106+
{isLoading ? (
107+
<ActivityIndicator size={12} color="#6e6e6b" />
108+
) : (
109+
<KindIcon size={12} color="#6e6e6b" />
110+
)}
111+
112+
{/* Tool name */}
113+
<Text
114+
className="font-mono text-[13px] text-neutral-200"
115+
numberOfLines={1}
116+
>
117+
{displayTitle}
54118
</Text>
55-
{isFailed && <Text className="text-red-400 text-xs">(Failed)</Text>}
119+
120+
{/* Failed indicator */}
121+
{isFailed && (
122+
<Text className="font-mono text-[13px] text-neutral-500">
123+
(Failed)
124+
</Text>
125+
)}
56126
</Pressable>
57127

128+
{/* Expanded content */}
58129
{isOpen && hasDetails && (
59-
<View className="mt-1 ml-6 overflow-hidden rounded-lg bg-dark-surface p-3">
130+
<View className="mt-2 ml-4">
60131
{args && (
61132
<View className="mb-2">
62-
<Text className="mb-1 font-medium text-dark-text-muted text-xs">
133+
<Text className="mb-1 font-mono text-[13px] text-neutral-400">
63134
Arguments
64135
</Text>
65-
<Text className="font-mono text-dark-text text-xs">
66-
{JSON.stringify(args, null, 2)}
67-
</Text>
136+
<View className="bg-amber-500/20 p-2">
137+
<Text className="font-mono text-[13px] text-amber-100">
138+
{JSON.stringify(args, null, 2)}
139+
</Text>
140+
</View>
68141
</View>
69142
)}
70143
{result !== undefined && (
71144
<View>
72-
<Text className="mb-1 font-medium text-dark-text-muted text-xs">
145+
<Text className="mb-1 font-mono text-[13px] text-neutral-400">
73146
Result
74147
</Text>
75-
<Text
76-
className="font-mono text-dark-text text-xs"
77-
numberOfLines={10}
78-
>
79-
{typeof result === "string"
80-
? result
81-
: JSON.stringify(result, null, 2)}
82-
</Text>
148+
<View className="bg-neutral-800/50 p-2">
149+
<Text
150+
className="font-mono text-[13px] text-neutral-300"
151+
numberOfLines={10}
152+
>
153+
{typeof result === "string"
154+
? result
155+
: JSON.stringify(result, null, 2)}
156+
</Text>
157+
</View>
83158
</View>
84159
)}
85160
</View>

0 commit comments

Comments
 (0)