แนวทาง

วิธีใช้ระบบให้สม่ำเสมอทุกหน้า ทั้งสองแบรนด์ อ่านก่อนสร้างหน้าใหม่หรือเพิ่มคอมโพเนนต์

ติดตั้ง

เลือกวิธีที่เหมาะกับโปรเจกต์ ทั้งสามวิธีใช้ CSS ชุดเดียวกัน

HTML ธรรมดา
<link rel="stylesheet" href="https://components.aswinology.com/ds/v1/ds.css">
<html lang="th" data-brand="aswinology">
Next.js: ฟอนต์
// app/layout.tsx: load only the fonts of the brand you ship
import { Archivo, Anuphan, Geist_Mono } from "next/font/google";            // ASWINOLOGY°
import { Inter_Tight, Geist, Noto_Sans_Thai, Geist_Mono } from "next/font/google"; // Lurnelle

const archivo = Archivo({ subsets: ["latin"], axes: ["wdth"], variable: "--f-archivo" });
const anuphan = Anuphan({ subsets: ["thai", "latin"], variable: "--f-anuphan" });
const mono = Geist_Mono({ subsets: ["latin"], variable: "--f-geist-mono" });

<html lang="th" data-brand="aswinology" className={`${archivo.variable} ${anuphan.variable} ${mono.variable}`}>

โค้ด React อยู่ในโฟลเดอร์ DESIGN-SYSTEM/ui ของ repo ASWINOLOGY คัดลอกทั้งโฟลเดอร์ไปเป็น @/ui แล้ว import สไตล์สามไฟล์ใน layout

หลักการ

  1. โทเคนก่อนค่าสี ทุกสี มุมโค้ง เงา และระยะ อ่านจากโทเคน ความต้องการใหม่กลายเป็นโทเคนใหม่ ไม่ใช่ค่าลอยๆ
  2. ใช้ของเบราว์เซอร์ก่อน dialog, details, select, input ได้การเข้าถึงและมือถือมาฟรี
  3. หนึ่งหน้าจอ หนึ่งเป้าหมาย ปุ่ม primary หนึ่งปุ่ม หัวข้อหนึ่งเรื่อง
  4. ไทยก่อน เขียน ทดสอบ และวัดระยะด้วยข้อความไทยจริง ไม่ใช่ lorem ipsum
  5. ซื่อตรง ไม่แต่งตัวเลข รีวิว ราคา หรือภาพบุคคล

รายการตรวจการเข้าถึง

ทุกคอมโพเนนต์ในไลบรารีผ่านรายการนี้แล้ว หน้าใหม่ต้องผ่านด้วย

ตัวอักษรไทย

ภาษาไทยมีสระบน สระล่าง และวรรณยุกต์ซ้อนกันได้สามชั้น ระยะที่ดีสำหรับอังกฤษจึงมักแน่นเกินไปสำหรับไทย

ช่องไฟติดลบ บรรทัด 1.0

ผู้เรียนที่กำลังเติบโต
ทุกวันไม่หยุดนิ่ง

ช่องไฟ 0 บรรทัด 1.25

ผู้เรียนที่กำลังเติบโต
ทุกวันไม่หยุดนิ่ง

  • หัวข้อไทยใช้ line-height อย่างน้อย 1.2 เนื้อหา 1.6 base.css ตั้งให้อัตโนมัติผ่าน :lang(th)
  • ไม่ใช้ตัวเอียงและไม่ใช้ตัวพิมพ์ใหญ่ทั้งคำกับข้อความไทย ใช้น้ำหนักหรือสีแทน
  • ใช้ text-wrap: balance กับหัวข้อ และตัดคำด้วยเว้นวรรคหรือ <wbr> เมื่อจำเป็น
  • ตัวเลขในตารางใช้เลขอารบิกและ tabular-nums

การเขียนใน UI

ใช้เมื่อไร

ควรทำ

  • ปุ่มขึ้นต้นด้วยกริยา ไม่เกินสามคำ: บันทึก, เริ่มเรียน
  • ข้อผิดพลาดบอกว่าเกิดอะไรและแก้อย่างไร
  • ใช้คำเดียวกันกับสิ่งเดียวกันทุกหน้า: คอร์ส ไม่ใช่สลับกับหลักสูตร
  • Lurnelle เรียกผู้ใช้ว่า คุณ

ไม่ควรทำ

  • ใช้เครื่องหมายตกใจในข้อความระบบ
  • ใช้ขีดยาว em dash ในข้อความ ใช้จุลภาคหรือขึ้นประโยคใหม่
  • เขียนว่า คลิกที่นี่ หรือ ดูเพิ่มเติม โดยไม่บอกปลายทาง
  • สัญญาผลลัพธ์ที่วัดไม่ได้ เช่น สอบติดแน่นอน

ลำดับของปุ่ม

หนึ่งหน้าจอมี primary ได้หนึ่งปุ่ม การกระทำรองใช้ secondary หรือ outline ยกเลิกใช้ ghost

  • ใน Dialog และฟอร์ม ปุ่มยืนยันอยู่ขวาสุด ปุ่มยกเลิกอยู่ทางซ้ายของมัน
  • danger ใช้เฉพาะการกระทำที่ย้อนกลับไม่ได้ และบอกผลในข้อความปุ่ม เช่น ลบถาวร
  • ถ้าย้อนกลับได้ ให้ทำทันทีแล้วแสดง Toast ที่มีปุ่มเลิกทำ แทนการถามยืนยัน

เลือก overlay ให้ถูก

คอมโพเนนต์ใช้เมื่อไม่ใช้เมื่อ
Dialogต้องหยุดผู้ใช้ เช่น ยืนยัน หรือฟอร์มสั้นเนื้อหายาว หรือข้อมูลที่ไม่เร่งด่วน
Sheetตัวกรอง เมนูมือถือ รายละเอียดข้างรายการการยืนยันสั้นๆ
Menuรายการคำสั่งของสิ่งหนึ่งการนำทางหลักของเว็บ
Tooltipชื่อของปุ่มไอคอน คำอธิบายศัพท์ข้อมูลจำเป็น หรือสิ่งที่กดได้
Toastผลของสิ่งที่ผู้ใช้เพิ่งทำข้อผิดพลาดของฟอร์ม ใช้ข้อความใต้ช่องแทน

สิ่งที่ไม่ควรทำ

ค่า hex ไม่เปลี่ยนตามแบรนด์และธีม

style={{ background: "#cdf46e" }}

แทนด้วย

style={{ background: "var(--accent)" }}

placeholder หายเมื่อพิมพ์ และคอนทราสต์ต่ำ

<input placeholder="อีเมล" />

แทนด้วย

<Field label="อีเมล"><Input /></Field>

โปรแกรมอ่านหน้าจอไม่รู้ว่าเปิดอะไรขึ้นมา

<Dialog trigger={…}>…</Dialog> // no title

แทนด้วย

<Dialog title="ลบคอร์สนี้ถาวร?" …>

ปุ่มไม่มีชื่อ

<Button iconOnly><Trash /></Button>

แทนด้วย

<Button iconOnly aria-label="ลบ"><Trash aria-hidden="true" /></Button>

วรรณยุกต์ชนกัน ตัวเอียงอ่านยาก

.thai-title { letter-spacing: -0.04em; font-style: italic; }

แทนด้วย

:lang(th) .title { letter-spacing: 0; }

ทำงานทุกเฟรมและไม่ล้างเมื่อออกจากหน้า

window.addEventListener("scroll", animate)

แทนด้วย

useGSAP(() => { /* ScrollTrigger */ }, { scope })

เพิ่มโทเคนหรือคอมโพเนนต์

แก้ที่ต้นทางเท่านั้น ไฟล์ CSS ของโทเคนและไฟล์ใน public/ds ถูกสร้างใหม่ทุกครั้งที่ dev หรือ build

เพิ่มโทเคน
// tokens/tokens.mjs
semantic: {
  "highlight": ["tint-butter", "#2a2410"],   // [light, dark]
}

// then
npm run tokens   // writes ui/styles/tokens.css and public/ds/v1/tokens.json
// the contrast table on /tokens updates on the next build
  1. เขียนคอมโพเนนต์ใน ui/ อ่านเฉพาะ semantic และ component token
  2. เพิ่มสไตล์ใน ui/styles/components.css คลาสขึ้นต้นด้วย ds- variant เป็น data-*
  3. เพิ่มหน้าเอกสารใน docs/components/ และรายการใน docs/registry.ts
  4. ตรวจทั้งสองแบรนด์ สองธีม จอ 375 px และคีย์บอร์ดอย่างเดียว