คำแนะนำการออกแบบ UI — บังคับใช้
ข้อบังคับสำหรับ ทุก ส่วนใหม่หรือเปลี่ยนแปลงของ UI ในแอปพลิเคชันนี้ (หน้า Blazor, ไดอะล็อก, คอมโพเนนต์)
นี่คือแหล่งข้อมูลดั้งเดิมที่อ้างอิงโดย CLAUDE.md หากกฎขัดขวางคุณ ให้หยุดและถามคำถาม — อย่าส่งมอบ UI ที่ละเมิดกฎนั้น มีรากฐานมาจาก plans/ui-overhaul.md
1. Mobile-first เสมอ
- เขียนโค้ดสำหรับโทรศัพท์ 360–430px ก่อน จากนั้นเพิ่มเติมขึ้นไปด้วย
min-widthmedia queries / prop MudBlazor breakpoint ไม่ใช่ desktop-first โดยใช้max-widthoverrides - ไม่มีการเลื่อนแนวนอนในทุกความกว้าง 320–1920px หากเนื้อหากว้างกว่า viewport จะถือว่าเป็นข้อบกพร่อง
- เป้าหมายการสัมผัส ≥ 44px (
var(--app-touch-target)) ฟอนต์ข้อความอินพุต ≥ 16px (ป้องกัน iOS zoom-on-focus) - เคารพ notches: ใช้
env(safe-area-inset-*); viewport ได้ตั้งค่าviewport-fit=coverแล้ว - เคารพ
prefers-reduced-motion— ไม่มีข้อมูลที่จำเป็นที่ถ่ายทำโดยแอนิเมชันเท่านั้น
2. Design tokens — ไม่มีค่าคงที่ยากเข้า
- สีทั้งหมด/radius/spacing มาจาก design tokens: MudBlazor theme (
Web/Components/Theme.cs) + CSS custom properties ที่ปล่อยออกมาจากWeb/Branding/BrandingCss.cs(var(--app-primary),--app-surface,--app-border,--app-text*,--app-radius, …) - ไม่ใช้รหัสสีฮex, radius หรือสตริง brand ไว้ในคอมโพเนนต์หรือกฎ CSS อ่านโทเค็น
Tokens ไหลมาจาก white-label
BrandingOptionsดังนั้นจานสีของผู้ขายต้องเข้าถึง UI ของคุณได้ฟรี - ค่าใหม่ที่ส่งผลต่อแบรนด์ → เพิ่มโทเค็น + เขตข้อมูล branding; อย่าฝังมันไว้
3. Responsive layout & data
- ตารางยุบเป็นการ์ดบนโทรศัพท์ ทุก
MudTableตั้งค่าBreakpoint="Breakpoint.Sm"และทุกMudTdมีDataLabelไม่มีตารางกว้างดั้งเดิมบนมือถือ (แม่แบบ:Components/Pages/Nodes.razor) - กริด:
MudItem xs="12" sm="6" md="4"— ความกว้างเต็มบนโทรศัพท์, หลายคอลัมน์ขึ้น - ฟอร์มแนวตั้งเดียวบนมือถือ; tap targets ขนาดใหญ่;
inputmode/autocompleteบนอินพุต; numeric/decimal inputmode สำหรับเงิน/เปอร์เซ็นต์ - ใช้คอนโทรลที่เหมาะสมสำหรับอินพุตที่มีโครงสร้าง — ไม่ใช่กล่องข้อความดั้งเดิมสำหรับตัวเลขหรือรายการ เก็บตัวเลข,
เงิน, เปอร์เซ็นต์, วันที่, enum และข้อมูลค่าหลายค่าใด ๆ ด้วยคอนโทรลที่ถูกต้อง (
MudNumericField,MudDatePicker,MudSelect, รายการแถวที่แก้ไขได้เพิ่ม/ลบ หรือตาราง) แต่ละเขตข้อมูล ได้รับการตรวจสอบความถูกต้องแยกต่างหากMudTextFieldฟรีข้อความเดียวที่ผู้ใช้ต้องพิมพ์ blob ที่คั่นด้วยเครื่องหมายจุลภาค/ช่องว่าง/ขึ้นบรรทัด จากนั้นคุณจะแยก — ห้ามใช้: ติดตั้งที่ไม่มีการตรวจสอบ และไม่เป็นมิตรกับโทรศัพท์ ไม่มีใครต้องการพิมพ์ blob อินพุตค่าหลายค่า คือรายการแถวแก้ไขได้ (เพิ่ม / ลบ) หรือโหลดจากข้อมูลโดเมนที่มีอยู่ (เช่น เรียกใช้การตรวจสอบโดยตรงจากการ backtest ที่เสร็จสิ้น แทนที่จะป้อนตัวเลขใหม่)MudTextFieldธรรมชาติ ใช้เฉพาะกับข้อความฟรีแท้ — ชื่อ, หมายเหตุ, ค้นหา, คำอธิบาย - จัดเตรียม โหลด, ว่าง, และข้อผิดพลาด สถานะในทุกรายการ/รายละเอียด — ขนาดสำหรับมือถือ
- การนำทาง ด้านล่างของมือถือ (
Components/Layout/BottomNav.razor) คือการนำทางโทรศัพท์หลัก; ลิ้นชักแบบจัดกลุ่มคือเมนูเต็ม เพิ่มจุดหมายปลายทาง high-traffic ที่นั่น; เก็บไว้ ≤5 รายการ
4. Dialogs (create/edit)
- การดำเนินการเพิ่ม/สร้าง/แก้ไข/ใหม่ทั้งหมดใช้ MudBlazor dialog (
IDialogService.ShowAsync<TDialog>), ไม่ใช่ แบบฟอร์มหน้าแบบ inline Dialogs อาศัยอยู่ในWeb/Components/Dialogs/เปิดเผย[Parameter]s, กลับมา nestedpublic sealed record …Result(...)การดำเนินการแถวรายการ (เริ่ม/หยุด/ลบ) อยู่แบบ inline เป็นปุ่มไอคอน - บนโทรศัพท์ ไดอะล็อกควร เต็มหน้าจอ / ความกว้างเต็ม และรู้จักแป้นพิมพ์
5. Inline help — ทุกคอนโทรล
- ทุกตัวเลือก, เลือก, สวิตช์, หรือการดำเนินการที่ไม่ชัดเจนจะได้รับ
<HelpTip Text="…" />(Components/HelpTip.razor) — hover บน desktop, แตะบนมือถือ ใช้ข้อความจากdocs/เพื่อให้ คำแนะนำอยู่ในการซิงค์กับพฤติกรรม; อัปเดตทั้งสองในการ commit เดียวกัน
6. White-label
- ชื่อผลิตภัณฑ์, โลโก้, คำอธิบาย, การสนับสนุน/บริษัท, สี, favicon ทั้งหมดมาจาก
BrandingOptionsอ้างอิงจากพวกมัน (IBrandingThemeProvider/IOptionsMonitor<AppOptions>), ไม่ใช่ "cMind" ตามตัวอักษรหรือ สีแบรนด์ manifest PWA, ไอคอน, theme-color, และ login hero ล้วนมีแบรนด์
7. PWA
- แอปสามารถติดตั้งได้ เก็บปลายจุด manifest (
/manifest.webmanifest) ไว้ที่มีแบรนด์, ไอคอนอยู่ (192/512/maskable + apple-touch), service worker app-shell-only (ไม่มีการสัมผัส Blazor circuit/_framework/hubs), และหน้าออนไลน์ทำงาน เส้นทางแบบ static ใหม่ → ให้ manifestscope - Blazor Server ต้องการวงจร SignalR ที่ใช้งานจริง → ติดตั้งได้ + app-shell, ไม่ใช่ offline เต็มรูปแบบ อย่า สัญญา interactivity offline
8. Accessibility
- ป้ายกำกับบนอินพุต,
aria-*บนคอนโทรลแบบกำหนดเอง, focus ที่มองเห็นได้, ลำดับ focus ตรรกะ เพราะ theme ปรับแต่งได้ตามไว ตรวจสอบ contrast กับ theme ที่ใช้งาน ไม่ใช่จาน palette ที่คงที่
9. E2E — ไม่มี UI ส่งมอบโดยไม่ได้ทดสอบ (blocking)
ทุกการเปลี่ยนแปลงที่หันหน้าไปยังผู้ใช้จัดส่ง Playwright E2E ใน tests/E2ETests, ขับเคลื่อนเหมือนผู้ใช้จริง, บน mobile
device emulation บวก desktop:
- เส้นทางใหม่ → เพิ่มไปที่
PageSmokeTestsและMobileLayoutTests(แสดงผล, bottom nav, ไม่มี UI ข้อผิดพลาด) - แปลงตาราง/หน้า → เพิ่มเส้นทางไปที่มือถือ no-overflow set
- ไหลใหม่ → การเดินทาง mobile ที่สมจริง (create/edit/save round-trip) และ unhappy path (อินพุตไม่ถูกต้อง, รายการว่าง, permission-denied ต่อบทบาท)
- ปลายเปลี่ยนความช่วยเหลือ → ยืนยันว่ามันเปิดบน tap (
HelpTipTestspattern) - ใช้
AppFixture.NewAuthedMobilePageAsync/NewAnonymousMobilePageAsync(device emulation) dotnet testสีเขียวก่อน "done" Emulated WebKit ≠ mobile Safari — real-device gating เป็นขั้นตอนการปล่อยแยกต่างหาก
10. Definition of done (UI)
- Mobile-first; ไม่มี overflow แนวนอน 320–1920px; touch targets ≥44px
- Design tokens เท่านั้น — ศูนย์สีคง/radii/brand strings ยากเข้า
- ตาราง → การ์ดบนโทรศัพท์ (
DataLabel+Breakpoint.Sm); โหลด/ว่าง/สถานะข้อผิดพลาดอยู่ - อินพุตที่มีโครงสร้างใช้คอนโทรลที่ถูกต้องที่ตรวจสอบความถูกต้อง (numeric/date/select/editable row list) — ไม่มี raw text box ที่ผู้ใช้พิมพ์ตัวเลข/ค่า blob ที่คั่นไว้ในนั้น
- สร้าง/แก้ไขผ่าน dialog; เต็มหน้าจออนมือถือ
- ทุกคอนโทรลมี
HelpTipที่มาจากเอกสาร - White-label + PWA ถูกเคารพ
- E2E มือถือ + desktop เพิ่ม (smoke, no-overflow, journey, unhappy path);
dotnet testสีเขียว - Rider
get_file_problems+dotnet format analyzersสะอาดบนไฟล์ที่สัมผัส