
助手對話介面 - Clean Architecture in TypeScript
透過 AI 協力開發,我們可以節省許多以往需要花費力氣的時間。不過開發的流程並不會有太大的變化,這次我們會採用可以馬上確認成果的方式進行開發,因此會從前端的介面開始著手。
初始畫面
我們希望在初期先建構一個可以跟助手(Assistant)對話的介面,基本上會需要訊息區域、對話輸入的區域,這部分我們會直接撰寫程式碼來作為提示。
我們先更新 src/client.tsx
把主畫面 App.tsx
引用進來,可以根據專案習慣使用像是 @/view
這種 Alias 設定,後續的範例都會直接使用這種風格。
1import { render } from "hono/jsx/dom";
2
3import { App } from "@/view/App";
4
5// @ts-ignore - This is a client-side only file
6const root = document.getElementById("root");
7if (root) {
8 render(<App />, root);
9}
接下來將 src/view/App.ts
也建立起來,裡面預計會引用一個 Chat
元件,用於後續我們製作的對話視窗。
1import { FC } from "hono/jsx/dom";
2
3import Chat from "@/view/Chat"
4import "@/view/style.css"
5
6export const App: FC = () => {
7 return (
8 <Chat />
9 );
10};
接著將 TailwindCSS 的基礎設定放到 src/view/style.css
裡面
1@import "tailwindcss";
最後先放一個 Hello World 的訊息到 src/view/Chat.tsx
裡面,確認 Hono JSX 的設定都正確運作,而且我們所需要的功能都按照預期。
1import { FC } from "hono/jsx/dom";
2
3export const Chat: FC = () => {
4 return (
5 <div>
6 <h1>Chat</h1>
7 <p>Welcome to the chat!</p>
8 </div>
9 );
10}
上述的任務可以利用 GitHub Copilot 的程式碼補完協力,雖然不是像代理模式(Agent Mode)那樣完全自動,但這可以幫助我們在過程中反思設計。
樣式設定
因為我們已經有 DESING.md
可以用作樣式的參考,所以可以先將 src/view/style.css
進行更新,利用 AI 來撰寫相應的設定。
受限於 TailwindCSS 4 比較新,我們會需要讓 AI 預先閱讀過 Theme 設定文件 以 Aider 為例子,會給予以下指示。
/read DESIGN.md
/web https://tailwindcss.com/docs/theme
完成之後,給予下面的提示詞,就會自動將 @theme
的內容產生出來。
According to `DESING.md` to add TailwindCSS theme config to `src/view/style.css`
根據使用的模型、編輯器不同結果可能會有差異,但我們預期至少要有類似下面這段 CSS 實作。
1@theme {
2 /* 顏色 */
3 --color-primary: #4F46E5;
4 --color-secondary: #6B7280;
5 --color-background: #F9FAFB;
6 --color-card: #FFFFFF;
7 --color-text-primary: #1F2937;
8 --color-text-secondary: #6B7280;
9
10 /* 排版 */
11 --font-sans: 'Inter', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica Neue', 'Arial', 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
12 --text-base: 1rem;
13 --font-weight-medium: 500;
14 --font-weight-bold: 700;
15 --leading-normal: 1.5;
16
17 /* 間距 */
18 --spacing-0: 0;
19 --spacing-2: 0.5rem;
20 --spacing-4: 1rem;
21 --spacing-6: 1.5rem;
22 --spacing-8: 2rem;
23
24 /* 邊框 */
25 --radius-md: 0.375rem;
26
27 /* 陰影 */
28 --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
29}
透過這種方式我們可以在編輯樣式上節省不少時間,必要時可能會需要自己去微調來確保符合預期,不一定要完全依賴使用 AI 編輯,有時候成本會遠大於自己修改一兩個字。
對話介面
接下來就要實際製作對話介面,我們預定要在 Chat
元件中增加 ChatMessage
和 ChatInput
兩個元件,此時腦中應該有大致上該有的實作雛形,但是細節我們可以先不考慮。
1import { FC } from "hono/jsx/dom";
2
3export const Chat: FC = () => {
4 // TODO: Manage Chat Message State
5
6 return (
7 <>
8 { /* TODO: Chat Message */ }
9 { /* TODO: Chat Input */ }
10 </>
11 );
12}
因為不需要自己實作,所以我們只需要把預期看到的成果用註解的方式記錄下來,在這個階段我們需要的是清楚知道 Chat
元件會保存對話訊息的狀態,而呈現則由 ChatMessage
和 ChatInput
兩個元件負責。
完成這個階段的處理後,先 git commit
把實作記錄下來,以免後續 AI 接手處理發生問題時,我們無法退回最後一次正常的狀態。
接下來根據你使用的 AI 工具給指示,目前已經設定 readonly: DESIGN.md
和 editable: src/view/Chat.tsx
兩組設定,明確限制我們只會改動到 Chat
元件,而且可以參考 DESIGN.md
的設計規範來套用介面。
Implement `ChatMessage` and `ChatInput` component for `Chat`.
* Create new component file
* Apply style according design token use TailwindCSS
* Use English in UI
* Use conventional commit in English
因為 AI 工具是具有隨機性的,上述的提示詞不一定能很好的運作。以撰寫這個段落時的情況,即使要求 Commit 訊息使用英文最後還是用中文撰寫,這可能是工具的 System Prompt 改變所造成。
但是在 AI 生成後,我們應該預期要能看到如下可操作的介面。
以往可能需要先學會怎麼管理 React 的狀態,以及實作對應的邏輯在調整樣式才能夠有這樣的效果,但我們可以在短短數分鐘內的幾此嘗試就取得這樣的成果,已經比過去開發更有效率不少。
生成的實作中仍可能會有一些問題,像是使用了
setTimeout
來模擬發送訊息的效果但沒有考慮 React 會重新產生的特性,一方面是因為我們並沒有交代不需要這樣的機制,另一方面也反應出 AI 不一定能判斷這種細節。
如果對這篇文章有興趣,可以透過以下連結繼續閱讀這系列的其他文章。
- 連載介紹 - Clean Architecture in TypeScript
- 目標設定 - Clean Architecture in TypeScript
- Hono 框架 - Clean Architecture in TypeScript
- tsyringe 套件 - Clean Architecture in TypeScript
- 專案設定 - Clean Architecture in TypeScript
- 介面規劃 - Clean Architecture in TypeScript
- 架構規劃 - Clean Architecture in TypeScript
- 助手對話介面 - Clean Architecture in TypeScript
- 對話紀錄 API - Clean Architecture in TypeScript