Skip to content

Commit 5219940

Browse files
koki-developclaude
andcommitted
refactor: split App.tsx into modular components
- Create src/components directory with separate components - Extract Message type to types.ts - Split MessageItem, ChatHistory, Spinner, and InputField into separate files - Simplify App.tsx to focus only on state management - Improve code maintainability and reusability 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent f79fe74 commit 5219940

File tree

6 files changed

+92
-33
lines changed

6 files changed

+92
-33
lines changed

src/App.tsx

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
1-
import { Box, Static, Text } from "ink";
2-
import Spinner from "ink-spinner";
3-
import TextInput from "ink-text-input";
1+
import { Box } from "ink";
42
import type React from "react";
53
import { useState } from "react";
6-
7-
interface Message {
8-
id: number;
9-
text: string;
10-
sender: "user" | "cat";
11-
}
4+
import { ChatHistory } from "./components/ChatHistory";
5+
import { InputField } from "./components/InputField";
6+
import { Spinner } from "./components/Spinner";
7+
import type { Message } from "./components/types";
128

139
export const App: React.FC = () => {
1410
const [messages, setMessages] = useState<Message[]>([]);
@@ -41,30 +37,14 @@ export const App: React.FC = () => {
4137

4238
return (
4339
<Box flexDirection="column">
44-
<Static items={messages}>
45-
{(message) => (
46-
<Box key={message.id} marginBottom={1}>
47-
<Text color={message.sender === "user" ? "cyan" : "green"}>
48-
{message.text}
49-
</Text>
50-
</Box>
51-
)}
52-
</Static>
53-
{isLoading && (
54-
<Box>
55-
<Spinner type="dots" />
56-
<Text> Thinking...</Text>
57-
</Box>
58-
)}
59-
<Box>
60-
<Text color="yellow">&gt; </Text>
61-
<TextInput
62-
value={input}
63-
onChange={setInput}
64-
onSubmit={handleSubmit}
65-
showCursor={!isLoading}
66-
/>
67-
</Box>
40+
<ChatHistory messages={messages} />
41+
{isLoading && <Spinner />}
42+
<InputField
43+
value={input}
44+
onChange={setInput}
45+
onSubmit={handleSubmit}
46+
showCursor={!isLoading}
47+
/>
6848
</Box>
6949
);
7050
};

src/components/ChatHistory.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Static } from "ink";
2+
import type React from "react";
3+
import { MessageItem } from "./MessageItem";
4+
import type { Message } from "./types";
5+
6+
interface ChatHistoryProps {
7+
messages: Message[];
8+
}
9+
10+
export const ChatHistory: React.FC<ChatHistoryProps> = ({ messages }) => {
11+
return (
12+
<Static items={messages}>
13+
{(message) => <MessageItem key={message.id} message={message} />}
14+
</Static>
15+
);
16+
};

src/components/InputField.tsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { Box, Text } from "ink";
2+
import TextInput from "ink-text-input";
3+
import type React from "react";
4+
5+
interface InputFieldProps {
6+
value: string;
7+
onChange: (value: string) => void;
8+
onSubmit: () => void;
9+
showCursor: boolean;
10+
}
11+
12+
export const InputField: React.FC<InputFieldProps> = ({
13+
value,
14+
onChange,
15+
onSubmit,
16+
showCursor,
17+
}) => {
18+
return (
19+
<Box>
20+
<Text color="yellow">&gt; </Text>
21+
<TextInput
22+
value={value}
23+
onChange={onChange}
24+
onSubmit={onSubmit}
25+
showCursor={showCursor}
26+
/>
27+
</Box>
28+
);
29+
};

src/components/MessageItem.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Box, Text } from "ink";
2+
import type React from "react";
3+
import type { Message } from "./types";
4+
5+
interface MessageItemProps {
6+
message: Message;
7+
}
8+
9+
export const MessageItem: React.FC<MessageItemProps> = ({ message }) => {
10+
return (
11+
<Box marginBottom={1}>
12+
<Text color={message.sender === "user" ? "cyan" : "green"}>
13+
{message.text}
14+
</Text>
15+
</Box>
16+
);
17+
};

src/components/Spinner.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Box, Text } from "ink";
2+
import InkSpinner from "ink-spinner";
3+
import type React from "react";
4+
5+
export const Spinner: React.FC = () => {
6+
return (
7+
<Box>
8+
<InkSpinner type="dots" />
9+
<Text> Thinking...</Text>
10+
</Box>
11+
);
12+
};

src/components/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export interface Message {
2+
id: number;
3+
text: string;
4+
sender: "user" | "cat";
5+
}

0 commit comments

Comments
 (0)