เพิ่มคอมโพเนนต์ UI · Adding a component
คอมโพเนนต์ของระบบดีไซน์อยู่ใน src/components/ui/ และ export ผ่าน src/components/ui/index.ts คู่มือฉบับเต็มเรื่องนี้ (TH + EN) อยู่ใน UI-FRAMEWORK.md หัวข้อ "Adding a component" หน้านี้สรุปขั้นตอนพร้อมเหตุผล
เมื่อไรควรสร้างคอมโพเนนต์ใหม่#
- รูปแบบ UI ถูกใช้ซ้ำ ตั้งแต่ 2 ที่ขึ้นไป หรือมีพฤติกรรมด้าน accessibility ที่ไม่อยากเขียนซ้ำ (focus, ARIA, keyboard)
- ถ้าใช้ที่เดียว ให้เขียนใน feature component ด้วย utility ตาม token ก็พอ
ขั้นตอน#
- เริ่มจาก Radix ถ้าโต้ตอบได้ (dialog, popover, tabs, toggle) ได้คีย์บอร์ด focus trap และ ARIA ครบ dependency ที่มีอยู่:
@radix-ui/react-{dialog,tabs,tooltip,switch,checkbox,toast,slot}ถ้าต้องเพิ่ม primitive ใหม่ ให้ระบุเหตุผลใน PR - สไตล์ด้วย semantic utilities เท่านั้น (
bg-surface,border-border,text-fg,text-muted,bg-primary text-primary-fg,text-link,rounded-xl,shadow-md,focus-ring,motion-base) ห้ามสีดิบ ห้ามdark:— ถ้าขาด token ให้เพิ่มในsrc/app/tokens.cssทั้ง:rootและ.dark, map ในglobals.css, เพิ่มในsrc/lib/design-tokens.tsและเพิ่มคู่ contrast ในtests/tokens.test.ts - ใช้
cn()(cn.ts) รวม className และรับclassNameจากภายนอก - ไอคอน: lucide-react สำหรับ UI (
h-4 w-4,aria-hidden),ToolIcon/ToolTileสำหรับโลโก้เครื่องมือ ห้ามอีโมจิ (test จะล้ม) - ข้อความ: รับผ่าน props หรือใช้
useLang()+ key ในsrc/lib/i18n.tsต้องมีทั้งไทยและอังกฤษ - export ใน
index.ts - แสดงใน
/design: เพิ่ม section ในsrc/components/design-system.tsx(ต่อท้ายSECTIONSเพื่อไม่ให้ index เดิมเลื่อน) พร้อมคำอธิบายสองภาษาและ usage snippet - test: เพิ่มใน
tests/ui-components.test.tsxอย่างน้อย: render, role/ชื่อที่เข้าถึงได้, พฤติกรรมคีย์บอร์ดหลัก - เอกสาร: อัปเดตตารางคอมโพเนนต์ใน
docs/UI-FRAMEWORK.mdและ CHANGELOG
กฎ accessibility (สรุป)#
- ปุ่มไอคอนอย่างเดียวต้องมี
aria-label - ใช้ element ที่ถูกความหมาย (
buttonสำหรับ action,aสำหรับนำทาง) — ใช้asChildเมื่อต้องการสไตล์ปุ่มบนลิงก์ - โฟกัสต้องมองเห็นได้ (
focus-ring) และลำดับ Tab สมเหตุสมผล - ข้อความต้องผ่าน AA (4.5:1) ทั้งสองธีม ส่วน non-text 3:1
- เคารพ
prefers-reduced-motion(ใช้ token duration ซึ่งเป็น 0.01ms อัตโนมัติ) - ภาษาไทย: อย่าใช้
leading-none/leading-tightกับเนื้อหาไทย
ข้อห้ามเชิงผลิตภัณฑ์#
การเพิ่มคอมโพเนนต์ ไม่ใช่ใบอนุญาตให้เปลี่ยนโครงสร้างหน้า การวางคอมโพเนนต์ใหม่ลงในหน้าที่มีอยู่ (เพิ่ม section) ต้องได้รับอนุญาตจากเจ้าของก่อน
ตรวจสอบ#
npm run lint && npm run typecheck && npm test จากนั้น npm run preview แล้วเปิด /design ทั้งสองธีมและสองภาษา ตรวจที่ความกว้าง 390px ว่าไม่มี horizontal scroll
Source: docs/contributing/add-component.md · /docs/contributing/add-component.md