ส่วนประกอบ UI (UI Components)
ภาพรวม
ชั้น UI ใช้ React + Ink สำหรับอินเทอร์เฟซผู้ใช้ใน terminal มี ~140 ส่วนประกอบ React ที่จัดระเบียบในสถาปัตยกรรมแบบโมดูลาร์และนำกลับมาใช้ใหม่ได้
โครงสร้างไดเรกทอรีส่วนประกอบ
src/components/
├── design-system/ - ส่วนประกอบพื้นฐานของการออกแบบ
├── MessageSelector.tsx - ส่วนประกอบกรองข้อความ
├── Spinner.js - ตัวบ่งชี้การโหลด
├── [140+ ไฟล์ส่วนประกอบ]
└── index.ts - การลงทะเบียนส่วนประกอบ
ระบบการออกแบบ
ระบบการออกแบบให้ส่วนประกอบพื้นฐานสำหรับการออกแบบที่สม่ำเสมอ:
src/components/design-system/
├── Box.tsx - คอนเทนเนอร์จัดระเบียบ
├── Text.tsx - การแสดงผลข้อความ
├── Button.tsx - ปุ่มเชิงโต้ตอบ
├── Input.tsx - ฟิลด์รับข้อความ
├── Modal.tsx - ไดอะล็อกแบบ modal
├── Card.tsx - คอนเทนเนอร์เนื้อหา
├── Badge.tsx - ตัวบ่งชี้สถานะ
└── [ส่วนประกอบพื้นฐานอื่นๆ]
หมวดหมู่ส่วนประกอบหลัก
ส่วนประกอบจัดระเบียบ
Box- คอนเทนเนอร์จัดระเบียบที่ยืดหยุ่นFlex- การจัดระเบียบแบบ flexboxGrid- ระบบการจัดระเบียบแบบ gridSpacer- ฟังก์ชันช่วยสำหรับการเว้นระยะ
ส่วนประกอบเชิงโต้ตอบ
Button- การกระทำที่คลิกได้Input- รับข้อความCheckbox- การเลือกแบบ booleanSelect- การเลือกแบบ dropdown
ส่วนประกอบตอบกลับ
Spinner- ตัวบ่งชี้การโหลดAlert- การแสดงการแจ้งเตือนProgress- แถบความคืบหน้าToast- ข้อความชั่วคราว
ส่วนประกอบเนื้อหา
Card- คอนเทนเนอร์เนื้อหาModal- ไดอะล็อกแบบ modalPanel- ส่วนที่พับได้Tooltip- ข้อมูลเมื่อชี้เมาส์
รูปแบบส่วนประกอบ
ส่วนประกอบทั้งหมดใช้รูปแบบที่สม่ำเสมอ:
// src/components/ExampleComponent.tsx
import React from 'react';
import { Box } from './design-system/Box.js';
export function ExampleComponent(props: ExampleProps) {
return (
<Box>
{/* เนื้อหาของส่วนประกอบ */}
</Box>
);
}
การจัดการสถานะของส่วนประกอบ
ส่วนประกอบใช้ React hooks สำหรับสถานะ:
import { useState, useEffect } from 'react';
export function InteractiveComponent() {
const [state, setState] = useState<StateType>(initialState);
useEffect(() => {
// หน้าที่ข้างเคียง
}, [dependencies]);
return (
<Box>
{/* แสดงผลตามสถานะ */}
</Box>
);
}
การผสานรวมส่วนประกอบกับเครื่องมือ
ส่วนประกอบ UI ของเครื่องมือจัดระเบียบแยกตามเครื่องมือ:
src/tools/<ToolName>/
├── <ToolName>Tool.ts - ตรรกะของเครื่องมือ
├── UI.tsx - ส่วนประกอบ UI เฉพาะเครื่องมือ
└── prompt.ts - system prompt
ตัวอย่าง: ส่วนประกอบ UI ของ BashTool
// src/tools/BashTool/UI.tsx
import React from 'react';
import { Box, Text } from '../../components/design-system';
export function BashToolUI(props: BashToolUIProps) {
return (
<Box>
<Text>ผลลัพธ์คำสั่ง Bash: {props.output}</Text>
</Box>
);
}
แนวปฏิบัติที่ดีของส่วนประกอบ
- Composability: ส่วนประกอบออกแบบสำหรับการซ้อนกัน
- การตรวจสอบ Props: การพิมพ์ TypeScript ที่เข้มงวด
- การจัดการสถานะ: ใช้ React hooks สำหรับสถานะท้องถิ่น
- การตกแต่ง: CSS-in-JS ผ่าน Ink
- การเข้าถึง: ARIA labels สำหรับ screen readers
การลงทะเบียนส่วนประกอบ
ส่วนประกอบถูกลงทะเบียนสำหรับการค้นหา:
// src/components/index.ts
export { Box } from './design-system/Box.js';
export { Text } from './design-system/Text.js';
export { Button } from './design-system/Button.js';
// ... ส่วนประกอบอื่นๆ ทั้งหมด
ประสิทธิภาพของส่วนประกอบ
- Memoization:
React.memoสำหรับการแสดงผลที่หนัก - Lazy Loading: โหลดส่วนประกอบหนักเมื่อต้องการ
- การแสดงผลตามเงื่อนไข: แสดงผลเฉพาะเมื่อจำเป็น
- การหน่วงเวลา events: ลดการแสดงผลซ้ำ
ความปลอดภัยของส่วนประกอบ
- ขอบเขตข้อผิดพลาด: แยกการล้มเหลวของส่วนประกอบ
- โหมด Permission: ส่วนประกอบปรับตามการตั้งค่า permission
- Feature Flags: ความพร้อมใช้งานของส่วนประกอบตามเงื่อนไข
- การแยกสถานะ: สถานะของส่วนประกอบแยกจากสถานะทั่วโลก
ตัวอย่างส่วนประกอบ
ส่วนประกอบ Spinner
// src/components/Spinner.js
export function Spinner(props: { mode?: SpinnerMode }) {
const mode = props.mode ?? 'dots';
// แสดงผลอนิเมชั่นการหมุน
return <Box>{/* อนิเมชั่น spinner */}</Box>;
}
ส่วนประกอบ Message Selector
// src/components/MessageSelector.tsx
export function MessageSelector(props: MessageSelectorProps) {
const { messages, onSelect } = props;
return (
<Box>
{messages.map(msg => (
<div key={msg.id} onClick={() => onSelect(msg)}>
{msg.content}
</div>
))}
</Box>
);
}
การทดสอบส่วนประกอบ
ส่วนประกอบถูกทดสอบผ่าน:
- การทดสอบหน่วย: พฤติกรรมของส่วนประกอบแต่ละตัว
- การทดสอบการผสานรวม: การโต้ตอบระหว่างส่วนประกอบ
- การทดสอบ E2E: กระบวนการ UI ทั้งหมด
เอกสารส่วนประกอบ
แต่ละส่วนประกอบมีเอกสารในตัว:
/**
* Box - คอนเทนเนอร์จัดระเบียบที่ยืดหยุ่น
*
* @param children - เนื้อหาที่จะแสดง
* @param style - สไตล์ CSS-in-JS
* @param className - ชื่อ class เพิ่มเติม (ถ้ามี)
*/
export function Box(props: BoxProps) {
// การดำเนินการ
}
ข้อควรพิจารณาด้านความปลอดภัยของส่วนประกอบ
- ไดเรกทอรีการทำงาน: ส่วนประกอบเคารพข้อจำกัดของ cwd
- โหมด Permission: ส่วนประกอบปรับตามการตั้งค่า permission
- Feature Flags: ความพร้อมใช้งานของส่วนประกอบตามเงื่อนไข
- การจัดการข้อผิดพลาด: การลดผลกระทบจากข้อผิดพลาดอย่างนุ่มนวล