UI ที่สม่ำเสมอในแอป React ด้วย design tokens และกฎคอมโพเนนต์
เรียนรู้การเขียนพรอมต์เพื่อ UI ที่สอดคล้องในแอป React โดยใช้ design tokens และกฎคอมโพเนนต์ เพื่อให้หน้าจอที่สร้างด้วย AI มีระยะห่าง ตัวอักษร และพฤติกรรมฟอร์มสอดคล้องกัน

ทำไมหน้าจอ React ที่ถูกสร้างมักดูไม่สอดคล้องกัน
ความไม่สอดคล้องของ UI มักปรากฏเป็นรายละเอียดเล็กๆ ที่รู้สึกแปลกเมื่อคุณคลิกไปรอบๆ หนึ่งหน้าอาจมี padding แบบกว้าง อีกหน้ารู้สึกคับแคบ หัวข้อกระโดดขนาด ปุ่มเปลี่ยนรูปทรงและสี และอินพุตเดียวกันทำงานต่างกันขึ้นอยู่กับหน้าจอ
ส่วนใหญ่แล้ว ความเบี่ยงเบนเกิดจากพื้นฐานไม่กี่อย่าง:
- ระยะห่าง: padding ช่องว่าง และจังหวะของส่วนต่างกัน
- ตัวอักษร: ขนาดน้ำหนักและ line-height ไม่คงที่
- คอมโพเนนต์: ปุ่ม การ์ด เส้นขอบ และเงาเปลี่ยนเล็กน้อย
- ฟอร์ม: เวลาในการตรวจสอบ ข้อผิดพลาดตำแหน่ง และสถานะ disabled ต่างกัน
สิ่งนี้เกิดขึ้นบ่อยเมื่อหน้าจอถูกสร้างจากพรอมต์แยกกัน แต่ละพรอมต์เป็นการเริ่มต้นใหม่ ดังนั้นแบบจำลองจึงเติมการตัดสินใจที่ขาดหายไปด้วยการเดา แม้คำว่า “ใช้สไตล์ร่วมสมัย” ก็ยังทิ้งการตัดสินใจนับร้อยไว้ให้เลือก: ช่องว่าง 8px กับ 12px ข้อความหลัก 14px กับ 16px จะแสดงข้อผิดพลาดเมื่อไหร่ ปุ่มหลักมีลักษณะอย่างไร
คุณอาจแก้สองสามหน้าด้วยมือได้ แต่ไม่สามารถขยายผลได้ คุณจะไล่แก้ CSS ทีละจุด คัดลอกสไตล์ข้ามไฟล์ และแก้ฟอร์มซ้ำๆ กฎอยู่ในหัวคุณ ไม่ได้อยู่ในโปรเจ็กต์
ลองจินตนาการสร้างหน้าล็อกอินวันนี้และหน้าประวัติพรุ่งนี้ ถ้าหนึ่งหน้าจอแสดงข้อผิดพลาดเฉพาะเมื่อกดส่ง แต่หน้าอื่นแสดงเมื่อ blur ผู้ใช้จะสังเกตได้ ถ้าความสูงปุ่มหลักเปลี่ยนระหว่างหน้าจอ แอปจะรู้สึกต่อกันไม่ดี
ความสอดคล้องจะกลายเป็นค่าปริยายเมื่อทุกหน้าจอปฏิบัติตามระบบร่วมกัน: design tokens (ระยะห่าง ตัวอักษร สี) บวกชุดกฎคอมโพเนนต์และฟอร์มขนาดเล็ก
Design tokens อธิบายง่ายๆ
Design tokens คือค่าที่ตั้งชื่อง่ายๆ ที่คุณนำกลับมาใช้ซ้ำทั่ว UI แทนที่จะขอ “padding แบบสบาย” ในทุกหน้าจอ ให้ใช้โทเค็นเช่น space-4 แทนคำว่า "เล็กน้อยโค้งมน" ให้ใช้ radius-md ชื่อจะคงที่แม้คุณจะเปลี่ยนค่าที่เชื่อมไว้ภายหลัง
โทเค็นคือชุดการตัดสินใจที่คุณต้องการให้ทุกหน้าจอแชร์ร่วมกัน พวกมันกำจัดรสนิยมและการเดา ซึ่งเป็นสาเหตุที่ทำให้เกิด drift เมื่อคุณสร้างหรือพัฒนาเพจใหม่
โทเค็นทั่วไปครอบคลุมระยะห่าง ตัวอักษร สี รูปร่าง และระดับความลึกเล็กน้อย ข้อดีเชิงปฎิบัติ: header ใช้ขนาดเดียวเสมอ การ์ดใช้ padding เดียวกันเสมอ และปุ่มหลักคงสีและรัศมีเดิม
อะไรควรถูกโทเค็น และอะไรควรยืดหยุ่น?
โทเค็นสิ่งที่มีผลต่อความรู้สึกโดยรวมของผลิตภัณฑ์: สเกลระยะห่าง ขนาดฟอนต์และ line-height สีหลัก (text, background, primary, danger, border) และชุดรัศมีขอบเล็กๆ
เก็บการตัดสินใจที่ขึ้นกับเนื้อหาให้ยืดหยุ่น เช่น ความยาวข้อความ ว่าใช้ไอคอนใด หรือว่าต้องการสองหรือสามการ์ดในส่วนหรือไม่
เมื่อคุณสร้างหน้าจอ (รวมถึงการใช้เครื่องมืออย่าง Koder.ai) การให้ชุดโทเค็นขนาดเล็กล่วงหน้าจะลดการเดาและทำให้ผลลัพธ์สอดคล้องมากขึ้น
เลือกชุดโทเค็นที่เล็กแต่ครบถ้วน
ชุดโทเค็นเป็นเพียงเมนูสั้นๆ ของค่าที่อนุญาต ยิ่งเล็กยิ่งดีเพราะลดโอกาสเลือกแบบสุ่ม แต่ยังต้องครอบคลุมพื้นฐานที่ทำให้หน้าจอรู้สึกผิดปกติ
เริ่มจากระยะห่าง เลือกสเกลหนึ่งและใช้ทั่วทั้งโปรเจ็กต์สำหรับ padding ช่องว่าง และเลย์เอาต์ ชุดเช่น 4, 8, 12, 16, 24, 32 ครอบคลุม UI ส่วนใหญ่ ถาดีไซน์ต้องการ 10px หรือ 18px ให้ปัดเป็นโทเค็นที่ใกล้ที่สุดแทนการเพิ่มตัวเลขใหม่
จากนั้นกำหนดค่าพื้นฐานของตัวอักษรเพื่อให้หัวข้อและตัวหนังสือหยุดไหลเบี่ยง คุณไม่จำเป็นต้องมีระบบตัวอักษรใหญ่โต แต่ต้องมีขั้นตอนชัดเจนที่ทำซ้ำได้
ชุดกะทัดรัดที่ยังใช้งานได้โดยไม่อืด:
- Spacing: 4, 8, 12, 16, 24, 32
- Type: ขนาดบอดี้หนึ่ง ขนาดหัวข้อสอง ค่า line-height หนึ่งสำหรับบอดี้ หนึ่งสำหรับหัวข้อ
- Colors: text-primary, text-muted, bg, surface, border, accent
- Radius: สองค่า (เช่น 4 และ 12)
- Elevation: none, small, medium (สามระดับสูงสุด)
การเข้าถึงควรอยู่ในระบบด้วย กำหนดสไตล์โฟกัส (สี ความหนา offset) เพื่อให้ผู้ใช้คีย์บอร์ดได้สถานะโฟกัสที่สม่ำเสมอ กำหนดขนาดเป้ากดขั้นต่ำ (เช่น 44x44) สำหรับมือถือ จำกัดสีตัวอักษรไว้ในชุดเล็กที่เชื่อถือได้เพื่อให้คอนทราสต์พยากรณ์ได้
ถ้าปุ่มบางครั้งดูอัดๆ มักเพราะหน้าหนึ่งใช้ padding 10 และอีกหน้าใช้ 12 ด้วยโทเค็นคุณสามารถบอกว่า: “ปุ่มใช้ paddingY=8, paddingX=16, radius=12, โทเค็นโฟกัส, min height 44.” เมื่อค่าพวกนี้ตายตัว เครื่องมือสร้างจะเลิกเดา
กฎคอมโพเนนต์ที่ทำให้ทุกหน้าจอสอดคล้อง
โทเค็นกำหนดตัวเลข กฎคอมโพเนนต์กำหนดนิสัย
เลือกชุดคอมโพเนนต์หลักเล็กๆ และถือว่าพวกมันเป็นบล็อกเดียวสำหรับหน้าจอ เก็บให้เรียบและนำกลับมาใช้ได้: Button, Input, Select, Checkbox, Card คุณสามารถเพิ่ม TextArea และ Modal แต่ต้องปฏิบัติตามระบบเดียวกัน (ป้าย ช่องว่าง สถานะ)
ถัดไป จำกัดตัวแปรและกำหนดเมื่อถึงอนุญาต เช่น: Button มี primary, secondary, และ danger Primary สำหรับการกระทำหลักบนหน้า (มักมีหนึ่งปุ่ม) Secondary สำหรับยกเลิกหรือลำดับความสำคัญต่ำ Danger เฉพาะสำหรับการกระทำทำลาย เช่น delete ถ้า variant อธิบายไม่ได้ ให้ใช้ secondary
กฎระยะห่างป้องกันการไหลเบี่ยง กำหนดค่าเริ่มต้นภายในคอมโพเนนต์: padding ปุ่ม ความสูงอินพุต ช่องว่างป้ายถึงฟิลด์ ช่องว่างมาตรฐานระหว่างฟิลด์ที่ซ้อนกัน เพิ่มกฎเลย์เอาต์บางอย่างด้วย: การ์ดมี padding ภายในคงที่และช่องว่างหัว/เนื้อหาที่สม่ำเสมอ Modal ใช้ขั้นความกว้างเดียวกันและจัดแนว footer แบบเดียวกัน
สุดท้าย ทำให้สถานะไม่สามารถโต้แย้งได้เพราะนี่คือที่ UI มักเริ่มดูสุ่ม:
- Loading: ปิดคอนโทรล แสดงสปินเนอร์ รักษาความกว้างให้คงที่
- Disabled: ลดคอนทราสต์ แต่ไม่ลบสไตล์ hover/focus ทั้งหมด
- Empty states: ข้อความสั้นพร้อมการกระทำหนึ่งอย่างชัดเจน
- Validation: ข้อผิดพลาดปรากฏใต้ฟิลด์และไม่ทำให้เลย์เอาต์กระโดด
เมื่อคุณสร้างหน้าที่มีฟอร์มหนักเช่น “Create project” กฎพวกนี้จะป้องกันขนาดปุ่มผสมกัน ตำแหน่งป้ายที่เลื่อน หรือ “การ์ดพิเศษ” ที่ปรากฏแค่หน้าหนึ่ง
กฎพฤติกรรมฟอร์ม: รายละเอียดที่มักไหลเบี่ยง
แม้จะมีภาพที่คงที่ แต่คำร้องเรียนว่า “มันรู้สึกแปลก” มักมาจากพฤติกรรมฟอร์ม ถ้าหนึ่งหน้าจอจัดการป้าย ข้อผิดพลาด และโฟกัสต่างกัน ผู้ใช้จะรับรู้ถึงความไม่สอดคล้อง
เลือกรูปแบบฟอร์มแบบเดียวและใช้มันทั่ว: ป้าย เครื่องหมาย optional/required ข้อความช่วยเหลือ แล้วข้อความผิดพลาด รักษาน้ำเสียงข้อความให้สอดคล้องด้วย (เช่น ป้ายใช้ตัวอักษรแบบ sentence case ข้อความช่วยสั้น และข้อความผิดพลาดขึ้นต้นด้วยคำกริยา)
กฎที่ป้องกันการ drift ส่วนใหญ่:
- ป้ายอยู่เหนือฟิลด์เสมอ (ไม่ใช้ placeholder เป็นป้าย)
- ข้อความช่วยเหลืออยู่ใต้ฟิลด์เสมอ ขนาดและสีเดียวกัน และไม่ใช้เป็นข้อผิดพลาด
- เวลาในการตรวจสอบ: แสดงข้อผิดพลาดหลัง blur หรือ submit ล้างเมื่อมีการเปลี่ยนแปลง
- ตำแหน่งข้อผิดพลาด: ข้อผิดพลาด 1 บรรทัดใต้ฟิลด์ ตรงกับตำแหน่งข้อความช่วย
- พฤติกรรมโฟกัส: ลำดับ Tab ตามเลย์เอาต์ที่มองเห็นได้; Enter ส่งข้อมูลเฉพาะเมื่ออยู่ในฟิลด์สุดท้ายหรือปุ่มหลักถูกโฟกัส
ล็อกขนาดและเลย์เอาต์เพื่อไม่ให้หน้าจอ “หายใจ” ต่างกัน กำหนดความสูงอินพุตหนึ่งค่า ความสูงปุ่มหนึ่งค่า และความกว้างฟิลด์เริ่มต้น บนเดสก์ท็อป จัดแนวฟิลด์ให้สอดคล้องกับกริดและวางป้ายเหนืออินพุต บนมือถือ ทำให้ฟิลด์เต็มความกว้างและหลีกเลี่ยงฟอร์มสองคอลัมน์ถ้าไม่จำเป็นจริงๆ
ตัวอย่างง่าย: หน้าจอ “Create project” อาจมี Name, Region, และ Description แม้ Region จะเป็น select ให้ปฏิบัติเหมือนฟิลด์อื่น: ความสูงเท่ากัน ตำแหน่งป้ายเดียวกัน และบรรทัดข้อผิดพลาดเดียวกัน ถ้าผู้ใช้ส่งฟอร์มโดยไม่ใส่ Name โฟกัสย้ายไปที่ Name ข้อผิดพลาดปรากฏใต้ และเลย์เอาต์คงที่
ถ้าคุณสร้างหน้าจอใน Koder.ai ให้ใส่กฎฟอร์มเหล่านี้ในพรอมต์ครั้งเดียวแล้วนำกลับมาใช้ข้ามฟีเจอร์ เพื่อให้ฟอร์มใหม่ทุกหน้าแสดงพฤติกรรมเดียวกันโดยไม่ต้องทำความสะอาดซ้ำ
วิธีแสดงโทเค็นและกฎในพรอมต์ของคุณ
ถือพรอมต์เป็นสัญญา UI ขนาดเล็ก จัดให้สั้น เฉพาะ และนำกลับมาใช้ได้ เพื่อให้หน้าจอใหม่ทุกหน้าสามารถยึดตามระยะห่าง ตัวอักษร คอมโพเนนต์ และพฤติกรรมเดียวกัน
รูปแบบปฏิบัติได้คือวางสเปค UI กะทัดรัดไว้ด้านบนคำขอ แล้วอธิบายหน้าจอด้วยภาษาธรรมดา
แม่แบบพรอมต์กะทัดรัด
UI SPEC (apply to every screen)
Tokens:
- Spacing: 4, 8, 12, 16, 24, 32
- Radius: 8
- Typography: H1 24/32, H2 18/26, Body 14/20
- Colors: text, muted, bg, primary, danger (no custom hex)
Components (must use): PageShell, Section, Card, Button, Input, Select, TextArea, FormRow, HelperText, Toast
Layout rules:
- Page padding: 24 desktop, 16 mobile
- Section spacing: 24
- Card padding: 16
- Grid: 12 cols desktop, 4 cols mobile, gap 16
Do:
- Reuse components and tokens only
- Keep labels above inputs, helper text below
Do not:
- Invent new spacing values, font sizes, or one-off CSS
- Mix different button heights or input styles
If a new component is needed:
- Extend an existing component pattern and document it in the output
- Do not create new visual styles outside tokens
หลังจากสเปค ให้เพิ่มการตรวจสอบการยอมรับเล็กๆ ที่จับการ drift ได้ตั้งแต่ต้น:
- “ใช้เฉพาะโทเค็นด้านบน; ห้ามใช้ inline styles.”
- “ฟอร์มทั้งหมดต้องใช้ FormRow และแสดงข้อผิดพลาดแบบเดียวกัน.”
- “ถ้าต้องเพิ่มคอมโพเนนต์ ให้สร้างบนพื้นฐาน Card พร้อมตัวอักษรที่มีอยู่.”
ถ้าคุณใช้เครื่องมือแบบแชท ให้เก็บสเปคนี้คงที่ข้ามคำขอ การเปลี่ยนมันบ่อยๆ จะทำลายจุดประสงค์
เวิร์กโฟลว์ที่รักษาความสอดคล้องของหน้าจอ
เขียนสัญญา UI ก่อนสร้างอะไรเลย: ชุดโทเค็นเล็กๆ (spacing, type, colors, radius, shadows) บวกรายการคอมโพเนนต์สั้นๆ (Button, Input, Select, Card, Modal, Table, Toast) ถ้าโทเค็นหรือคอมโพเนนต์หายไป แบบจำลองจะคิดขึ้นมาและ UI ของคุณจะ drift
จากนั้นสร้างหน้าจออ้างอิงเดียวที่ทดสอบกฎ หน้าที่มีฟอร์มหนักเป็นการทดสอบที่ดีเพราะมีหัวข้อ ข้อความช่วย ข้อผิดพลาดป้อนเข้า ปุ่มหลักและรอง และ toast สำเร็จ ถือหน้าจอนั้นเป็นเบสไลน์
จากตรงนั้น สร้างหน้าจอใหม่ด้วยการประกอบสิ่งที่คุณกำหนดไว้แล้ว อย่าขอ “สไตลิ่งใหม่” ให้ขอการ์ดเดียวกัน สเกลระยะห่างเดียวกัน ขั้นตัวอักษรเดียวกัน และรูปแบบฟิลด์เดิม
เวิร์กโฟลว์ง่ายๆ:
- ยืนยันโทเค็นและกฎคอมโพเนนต์ แล้วแช่แข็งสำหรับฟีเจอร์
- สร้างหน้าจออ้างอิงหนึ่งหน้าและปรับสเปคจนพอใจ
- สร้างหน้าจอใหม่โดยนำคอมโพเนนต์มาใช้ซ้ำ ไม่ใช่ทำสไตลิ่งใหม่
- ตรวจทานความสอดคล้อง แล้วเปลี่ยนกฎ (โทเค็น/คอมโพเนนต์) ไม่ใช่การแก้จุดเล็กๆ
- บันทึกสเปคเป็นสเน็ปเพื่อนำกลับมาใช้ในฟีเจอร์ถัดไป
ถ้าหน้า “Search users” มีระยะห่างคับกว่าเบสไลน์ อย่าแก้ margin ทีละจุด ปรับ spacing token หรือกฎ Card padding แล้วสร้างใหม่
ถ้าคุณใช้ Koder.ai, snapshots และ rollback ช่วยได้: ล็อกเบสไลน์ ทดลองอย่างปลอดภัย และย้อนกลับเร็วถ้ามีการเปลี่ยนที่เริ่มทำให้เกิด drift
ข้อผิดพลาดทั่วไปที่ควรหลีกเลี่ยง
วิธีที่เร็วที่สุดในการเสียความสอดคล้องคือมองโทเค็นและกฎเป็นเพียงคำแนะนำ ข้อยกเว้นเล็กๆ จะทวีคูณเมื่อสร้างหน้าจอใหม่
หนึ่งกับดักคือการเปลี่ยนสเกลระยะห่างกลางโปรเจ็กต์ หน้าต้นใช้ 8, 16, 24 หน้าถัดมานำ 10 และ 18 เข้ามา “เพราะมันดูดี” ตอนนี้ drift ได้รับอนุญาตและหน้าก่อนหน้าไม่ถูกอัปเดต
แหล่งที่มาของ drift อีกอย่างคือปล่อยให้เครื่องมือสร้างสไตล์คอมโพเนนต์ใหม่ หากคุณไม่บอกว่า “มีเฉพาะปุ่มแบบนี้” มันอาจสร้างรัศมีใหม่หรือ padding อินพุตที่ต่างกันในหน้าหนึ่ง
สถานะก็เป็นอีกจุดที่มักพลาด Loading, empty, และ error มักเปลี่ยนระยะห่างและพฤติกรรม ถ้าคุณยัดมันเข้าไปท้ายๆ มักได้รูปแบบที่รีบทำและไม่เข้ากับส่วนที่เหลือ
ระวังความกำกวมแบบนี้: “ทำให้มันโมเดิร์นด้วยเงาอ่อนๆ” ฟังดูคลุมเครือ ขณะที่กฎพฤติกรรมเช่น “ข้อผิดพลาดแสดงใต้ฟิลด์”, “ปุ่ม disabled ยังมีสไตล์โฟกัส”, และ “Enter ส่งเฉพาะในฟิลด์สุดท้าย” มีความชัดเจนและทำซ้ำได้
ถ้าต้องการการ์ดการ์ดเล็กๆ สำหรับวางในพรอมต์ ให้สั้น:
- ใช้สเกลระยะห่างและโทเค็นตัวอักษรเดียวกับหน้าจอที่มีอยู่; อย่าประดิษฐ์ค่ามาใหม่
- ใช้คอมโพเนนต์และ variant ที่อนุญาตเท่านั้น
- รวมสถานะ loading, empty, error โดยใช้โทเค็นเดิม
- กำหนดพฤติกรรม (validation, focus order, submit, disabled) ให้ชัดเจนเหมือนกับภาพ
เช็คลิสต์ความสอดคล้องด่วนก่อนยอมรับหน้าจอ
ก่อนผสานหน้าจอที่สร้าง ให้สแกนสองนาที
เริ่มจากระยะห่าง มองหาค่าที่สุ่มเช่น 13px หรือ margin พิเศษที่เพิ่ม “เพื่อให้เข้าที่” ถ้าใช้โทเค็น ทุกช่องว่างควรมาจากชุดที่อนุญาต รวม gutters padding การ์ด และช่องว่างระหว่างฟิลด์ฟอร์ม
จากนั้นตรวจตัวอักษรกับสเกลหัวข้อ หัวข้อควรลดขนาดอย่างสม่ำเสมอ ข้อความปกติไม่ควรสลับขนาดระหว่างส่วนที่คล้ายกัน line-height สำคัญโดยเฉพาะในหน้าที่แน่นเช่นหน้าการตั้งค่า
สแกนปุ่มต่อไป variant และขนาดควรตามกฎของคุณ: primary สำหรับการกระทำหลัก secondary สำหรับการกระทำสำคัญน้อยกว่า danger เฉพาะเมื่อลบ ขนาดปุ่ม การวางไอคอน และสไตล์ป้ายควรตรงกัน
สำหรับฟอร์ม ความสอดคล้องส่วนใหญ่เกี่ยวกับโครงสร้าง ป้ายอยู่ที่เดียว ตัวบ่งชี้ required ตามกฎเดียว ข้อความช่วยและข้อผิดพลาดไม่แข่งขันกัน และข้อผิดพลาดปรากฏที่ตำแหน่งเดียวกัน
เช็คลิสต์สั้นๆ:
- ระยะห่างใช้เฉพาะค่าจากโทเค็น (ไม่มีตัวเลขสุ่ม)
- แบบอักษรตรงตามสเกล (รวม line-height)
- ปุ่มตาม variant และขนาดเดียวกัน
- ฟอร์มใช้รูปแบบเดียวสำหรับป้าย ข้อความช่วย และข้อผิดพลาด
- มีสถานะ: hover, focus, disabled, loading, empty
สุดท้าย ทดสอบมือถือ ย่อความกว้างและยืนยันว่าเลย์เอาต์ปรับโดยไม่ประดิษฐ์ขนาดฟอนต์หรือระยะห่างใหม่
ตัวอย่าง: สร้างฟีเจอร์ React เล็กๆ โดยไม่ให้เกิด style drift
สมมติ onboarding สั้นๆ: สามหน้าจอ (Profile, Preferences, Confirm) บวกหน้า Settings ในภายหลัง คุณต้องการให้แต่ละหน้ารู้สึกเหมือนมาจากผู้ดีไซน์เดียวกัน แม้จะสร้างแยกกัน
ก่อนสร้างอะไร ให้ระบุชุดโทเค็นและกฎคอมโพเนนต์สั้นๆ:
TOKENS
- spacing: xs=4, sm=8, md=12, lg=16, xl=24
- radius: sm=8, md=12
- type: body=14/20, title=20/28, label=12/16
- layout: pageMax=960, sectionGap=24, fieldGap=12
COMPONENT RULES
- Page: max width=pageMax, padding=xl, sectionGap between blocks
- Card: padding=lg, radius=md
- Field: label above, helper below, fieldGap between fields
- Button row: primary on right, gap=sm
- Errors: shown under field, same copy style, no alerts
ตอนนี้สร้าง “Profile” และ “Preferences” แยกกัน เพราะทั้งสองหน้าต้องใช้ Page, Card, Field, และ Button row ตามที่นิยามไว้ พวกมันจะได้ margin ช่องว่างป้าย และตำแหน่งปุ่มเดียวกัน ขั้นตอน Confirm ยังเข้ากันได้แม้ว่าจะมีข้อความอ่านอย่างเดียวมากขึ้น
พฤติกรรมฟอร์มคือที่ที่ drift มักแอบซ่อน ดังนั้นกำหนดครั้งเดียวแล้วนำกลับมาใช้: ปุ่มส่งปิดจนกว่าจะ valid ข้อผิดพลาดแสดงหลัง blur หรือ submit เท่านั้น Enter ส่งเฉพาะในขั้นตอนสุดท้าย และปุ่ม Back ไม่เคลียร์ค่าที่ป้อนแล้ว
เมื่อคุณต้องการชิ้น UI ใหม่ อย่าปล่อยให้แบบจำลองสวมบทบาท ให้เพิ่มกฎเดียว แล้วสร้างใหม่โดยคำนึงถึงการนำกลับมาใช้:
- ProgressStepper: height=32, spacing=md, current step bold, completed steps clickable
ขั้นตอนถัดไป: ทำให้ความสอดคล้องเป็นค่าปกติ
เปลี่ยนโทเค็นและกฎเป็นสเปคที่นำกลับมาใช้จริง ถ้ามันยาวเกินไปที่จะวาง พรอมต์จะไม่ถูกปฏิบัติตาม
สเปคที่ปฏิบัติได้มักประกอบด้วย: ตารางโทเค็นของคุณ (spacing, type, radii, colors) ชุดกฎคอมโพเนนต์สั้นๆ (buttons, inputs, cards, headings) กฎพฤติกรรมฟอร์ม (เวลา validation, ข้อผิดพลาด, disabled/loading) ค่าเริ่มต้นเลย์เอาต์ (padding หน้า ความกว้างสูงสุด ช่องว่างส่วน) และรายการสั้นๆ ของสิ่งที่ห้ามทำ (margin สุ่ม ขนาดฟอนต์ ad-hoc)
แล้วสร้างนิสัยหนึ่งอย่าง: อัปเดตสเปคก่อน ไม่ใช่พิกเซลเดี่ยว
ถ้าคุณใช้ Koder.ai (koder.ai), planning mode เป็นที่ที่ดีในการยืนยันสเปคก่อนสร้าง UI เมื่อต้องการลองทางเลือก snapshot และ rollback ช่วยให้สำรวจได้โดยไม่ทำลายเบสไลน์ที่เสถียร
คำถามที่พบบ่อย
ทำไมหน้าจอ React ที่ถูกสร้างจึงดูไม่สอดคล้อง ถึงแม้ผมจะขอให้ใช้ “สไตล์ร่วมสมัย”?
เพราะแต่ละคำขอหน้าจอเป็นการเริ่มต้นใหม่ หากคุณไม่ให้ระบบร่วมกัน เครื่องมือจะเติมรายละเอียดที่ขาดด้วยการเดา—ระยะห่าง ขนาดฟอนต์ การเว้นที่ปุ่ม เงา และพฤติกรรมฟอร์ม—จึงเกิดความแตกต่างเล็กๆ น้อยๆ สะสมข้ามหน้าจอ
Design tokens คืออะไรแบบง่ายๆ และช่วยได้อย่างไร?
Design tokens คือ ค่าที่ตั้งชื่อและนำกลับมาใช้ได้ สำหรับสิ่งต่างๆ เช่น ระยะห่าง ขนาดตัวอักษร สี และรัศมีมุม
แทนที่จะบอกว่า “padding แบบสบาย ๆ” ให้ใช้เช่น space-md ชื่อจะคงที่ แม้คุณจะเปลี่ยนค่าที่แมปไว้ในภายหลัง หน้าจอทุกหน้าใช้การตัดสินใจเดียวกัน จึงลดการ drift ได้
ชุดโทเค็นขนาดเล็กแต่ครบถ้วนที่ดีเริ่มต้นด้วยอะไร?
เริ่มจากขนาดเล็กและครอบคลุมเฉพาะสิ่งที่ทำให้เกิดความแตกต่างที่เห็นได้ชัด:
- Spacing: 4, 8, 12, 16, 24, 32
- Type: ขนาดบอดี้ 1 ตัว + ขนาดหัวข้อ 2 ตัว + line-height ตายตัว
- Colors: text, muted, bg, surface, border, primary, danger
- Radius: 2 ค่า (เช่น 8 และ 12)
- Elevation: none, small, medium
ถ้าต้องการค่าใหม่ ให้ปัดเป็นโทเค็นที่ใกล้ที่สุดแทนการสร้าง 10px หรือ 18px ขึ้นมาใหม่
ผมจะเขียนพรอมต์อย่างไรให้ทุกหน้าจอที่สร้างออกมาสอดคล้องกัน?
วางบล็อกสเปค UI ขนาดกะทัดรัดไว้ด้านบนของคำขอแต่ละครั้ง และถือเป็นสัญญา:
- ระบุโทเค็น (spacing/type/colors/radius)
- ระบุคอมโพเนนต์ที่อนุญาต (Button, Input, Card ฯลฯ)
- เพิ่มกฎเข้มงวด (ไม่ใช้ค่า spacing ใหม่ ไม่ทำ inline styles)
แล้วอธิบายหน้าจอด้านล่าง สเปคนี้ต้องไม่เปลี่ยนข้ามหน้าจอเพื่อให้ผลคงที่
กฎคอมโพเนนต์แบบไหนที่ป้องกันการ drift ได้มากที่สุด?
โทเค็นกำหนดตัวเลข; กฎคอมโพเนนต์กำหนดนิสัย กฎที่เป็นประโยชน์ได้แก่:
- ปุ่ม: ความสูงตายตัว ระยะในปุ่ม และมีเฉพาะไม่กี่แบบ (primary/secondary/danger)
- อินพุต: ความสูงเดียว ช่องว่างป้ายชัดเจน สไตล์เส้นขอบ/โฟกัสสม่ำเสมอ
- Card: padding ตายตัว และช่องว่างหัว/เนื้อหาที่คาดเดาได้
- เลย์เอาต์: padding หน้าและช่องว่างระหว่างส่วนมาตรฐาน
กฎเริ่มต้น: ถ้าไม่สามารถหาเหตุผลสำหรับ variant ใหม่ ให้กลับไปใช้แบบมาตรฐาน
การตรวจสอบฟอร์มและตำแหน่งข้อผิดพลาดที่ดีที่สุดคืออะไร?
เลือกแบบหนึ่งแล้วใช้ให้ทั่ว:
- ป้ายอยู่เหนือฟิลด์เสมอ (อย่าใช้ placeholder เป็นป้าย)
- ข้อความช่วยเหลืออยู่ด้านล่างฟิลด์ (ไม่ใช้สำหรับข้อผิดพลาด)
- ข้อความผิดพลาด 1 บรรทัด ใต้ฟิลด์โดยตรง
- แสดงข้อผิดพลาด หลังจาก blur หรือ submit และเคลียร์เมื่อมีการเปลี่ยนแปลง
วิธีนี้หลีกเลี่ยงปัญหา “หน้าจอหนึ่งตรวจสอบตอน blur อีกหน้าหนึ่งตรวจสอบตอน submit” ซึ่งผู้ใช้สังเกตได้
ควรทำมาตรฐานสถานะ UI แบบไหนบ้างเพื่อไม่ให้หน้าจอดูสุ่ม?
กำหนดกฎสถานะที่ไม่ยอมต่อรอง:
- Loading: ปิดการใช้งานคอนโทรล แสดงสปินเนอร์ และรักษาความกว้างให้คงที่
- Disabled: ลดคอนทราสต์ แต่ยังคงพฤติกรรมโฟกัสไว้
- Empty state: ข้อความสั้น + การกระทำชัดเจนหนึ่งอย่าง
- Errors: แบบอินไลน์ใต้ฟิลด์; หลีกเลี่ยงการกระทบเลย์เอาต์ใหญ่
ถ้าไม่กำหนดสถานะ แต่ละหน้าจะมักคิดรูปแบบของตัวเองขึ้นมา
ควรทำอย่างไรเมื่อหน้าจอต้องการคอมโพเนนต์ใหม่ที่ยังไม่มีในรายการ?
อย่าให้มันประดิษฐ์สไตลิ่งเอง ให้เพิ่มเป็นการ ขยายที่มีเอกสาร ของรูปแบบที่มีอยู่:
- สร้างคอมโพเนนต์ใหม่โดยอ้างอิงโทเค็นปัจจุบันและคอนเทนเนอร์ที่คุ้นเคย (มักเป็น Card)
- กำหนดขนาด ช่องว่าง และสถานะโดยใช้โทเค็นที่มี
- เพิ่มเข้าไปในรายการคอมโพเนนต์ที่อนุญาตสำหรับหน้าถัดไป
ถ้าคุณอธิบายมันไม่ได้ด้วยโทเค็น มันมักจะเป็นของที่เฉพาะเกินไปและจะทำให้เกิด drift
เวิร์กโฟลว์แบบไหนที่รักษาความสม่ำเสมอเมื่อสร้างหน้าจอหลายเซสชัน?
สร้างหน้าจออ้างอิงที่ทดสอบระบบให้ดี (หน้าแบบฟอร์มหนักๆ ดีมาก) แล้วนำสเปคเดิมมาใช้กับหน้าที่สร้างใหม่ทุกครั้ง
ใน Koder.ai คุณสามารถใช้ planning mode เพื่อยืนยันสเปคก่อนสร้าง และใช้ snapshots และ rollback เพื่อรักษาเบสไลน์ที่เสถียรขณะที่ทดลอง
มีเช็คลิสต์รวดเร็วอะไรบ้างเพื่อตรวจจับความไม่สอดคล้องก่อนผสานโค้ด?
สแกนอย่างรวดเร็วก่อนยอมรับหน้าจอ:
- ระยะห่างใช้เฉพาะค่าจากโทเค็น (ไม่มีตัวเลขสุ่ม)
- แบบอักษรตรงตามสเกล (รวม line-height)
- ปุ่มตามรูปแบบและขนาดเดียวกัน
- ฟอร์มมีโครงสร้างป้าย/ข้อความช่วย/ข้อผิดพลาดแบบเดียวกัน
- มีสถานะ: hover, focus, disabled, loading, empty
ถ้ามีบางอย่างผิด ให้ปรับสเปค/โทเค็นแล้วสร้างใหม่—อย่าแพตช์ margin แบบครั้งเดียว