genesis+worker: design system Genesis ทั้งชุด + patch pdf.worker แก้ fake-space ไทย + ปิด review design/responsive/quality รอบ 2026-09-24 — (1) Genesis: ฟอนต์ General Sans self-host + DM Sans + Sarabun, AppNav 56px backdrop-blur แทน SessionBar, DotGrid หน้า login, palette/รัศมี/เงา/focus ตาม docs/DESIGN.md ครบทุกหน้า (2) postinstall scripts/patch-pdf-worker.mjs ถอด if (scaledDim) รอบ prevTransform ให้อัปเดตทุก glyph — กัน addFakeSpaces แทรก space กลางคำไทยใน PDF ที่ justify ด้วย letter-spacing + test กัน regression (tests/scripts/ + fixture thai_letterspacing.pdf, invariant #6) (3) ฟอร์มอัปโหลด + ช่องกลุ่ม typeId ทางเลือก — normDocumentGroup ที่ utils/external-file.ts เป็น single source ร่วมกับ N8 (4) token fixes: focus ring ปุ่ม pin + แถว bookmark ตามหน้า, ปุ่ม action ใน popup/composer/dialog เป็น rounded-md ทั้งคู่, selection preview เป็น tint ของ primary แทน blue-500 ดิบ, default สี shape/highlight รวมที่ utils/annotation-display, loading animate-pulse + จดข้อยกเว้น (เงา pin, font weights ของ viewer) ลง DESIGN.md (5) responsive: Export PDF max-lg:order-first ให้เห็นบน iPad, แถวบน header แถวเดียวเลื่อนได้บนจอแคบ, re-fit ความกว้างตอน toggle sidebar เฉพาะเมื่อยังไม่ซูมเอง, pin popover flip ขึ้นบนเมื่อใกล้ท้ายหน้า, toast hint ตอนสลับ tool กลางเอกสาร, ป้าย "ชนิด · ผู้ทำ" ของรายการผู้อื่นสำหรับจอสัมผัส (6) คุณภาพ: @layer ครอบ @media กันกฎ touch รั่ยไป desktop (Tailwind v3 ยก @layer ออกจาก media ทิ้ง wrapper — ยืนยันด้วย build จริง + วัดบนจอ), กฎ M5 ครอบ contenteditable กัน Safari zoom ตอนแก้ไข TEXTBOX บน iPad, COMMENT ใช้ box มาตราฐานเดียวตาม pin px จริง (render/scroll target/move-clamp/bookmark), ตัดหัวการ์ดซ้ำกับ h2 หน้ารายการ — พร้อมไฟล์ untracked ที่ postinstall/โค้ดอ้างถึงครบชุด (app/fonts/, AppNav, DotGrid, tests/) กัน fresh clone fail ที่ npm install (คำขอผู้ใช้ 2026-09-24)
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
parent
e254b935ce
commit
c5c6b65bd2
42 changed files with 1429 additions and 745 deletions
114
app/globals.css
114
app/globals.css
|
|
@ -2,6 +2,22 @@
|
|||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
/* ─── Genesis utilities (docs/DESIGN.md 2026-09-23) ────────────────────────
|
||||
focus indicator = outline น้ำเงินทึบ 2px + offset 2px ของ design system — แยกเป็น
|
||||
class ร่วมเพื่อใช้ซ้ำทุกปุ่ม/ลิงก์; input ใช้ .genesis-input (ขอบน้ำเงิน + outline ตอน
|
||||
:focus ตาม spec Inputs) — ครอบด้วย @layer components ให้ Tailwind utilities ทับได้
|
||||
(UX review M3 2026-09-23: halo alpha 0.12 ของ spec เดิม blend บนขาวแล้ว ~1.2:1
|
||||
ต่ำกว่าเกณฑ์ 3:1 ของ WCAG 1.4.11 — alpha 0.25–0.35 ก็ยังไม่ผ่าน จึงเปลี่ยนเป็น
|
||||
outline ทึบเป็นตัวชี้วัด + offset คั่นไม่ให้จมกับพื้นปุ่ม primary) */
|
||||
@layer components {
|
||||
.focus-ring {
|
||||
@apply focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary;
|
||||
}
|
||||
.genesis-input {
|
||||
@apply rounded-md border border-line bg-white px-3.5 py-2 text-sm text-ink placeholder:text-ink-faint focus:border-primary focus:outline focus:outline-2 focus:outline-offset-1 focus:outline-primary;
|
||||
}
|
||||
}
|
||||
|
||||
/* ─── TextLayer ของ pdfjs v4 ─────────────────────────────────────────────────
|
||||
คัดมาจาก node_modules/pdfjs-dist/web/pdf_viewer.css (ส่วนที่จำเป็น)
|
||||
ใช้กับ pdfjs.TextLayer ที่ render ลง div.textLayer ใน PDFViewer */
|
||||
|
|
@ -136,10 +152,15 @@
|
|||
inset: -4px;
|
||||
}
|
||||
|
||||
/* ปุ่ม bookmark/ลบในแผง selection (20×20) + swatch สีในแผง (16×16) */
|
||||
/* ปุ่ม bookmark/ลบในแผง selection (20×20) + swatch สีในแผง (16×16) —
|
||||
sel-panel-btn ใส่ centering แบบ .coarse-36 กันผู้ใช้ class ไม่ได้เอา flex
|
||||
มาเอง (ไอคอนลอยชิดบนในกล่อง 36px); ปุ่มที่ใช้อยู่มี flex แล้ว ผลลัพธ์ไม่เปลี่ยน */
|
||||
.sel-panel-btn {
|
||||
min-height: 2.25rem;
|
||||
min-width: 2.25rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.sel-panel .color-swatches button,
|
||||
.sel-panel .color-swatches label {
|
||||
|
|
@ -226,6 +247,59 @@
|
|||
main.summary-page button {
|
||||
min-height: 2.75rem;
|
||||
}
|
||||
|
||||
/* UX review M5 2026-09-23: ช่องกรอกทุกชนิด ≥16px บนจอสัมผัส — iOS Safari ซูมทั้ง
|
||||
หน้าทุกครั้งที่แตะโฟกัสช่องที่ตัวอักษรเล็กกว่า 16px (ทีมตั้งกติกาเดียวกันไว้
|
||||
หน้า login แล้ว — ขยายครบทุกช่องของแอปเฉพาะอุปกรณ์จอสัมผัส; !important จำเป็น
|
||||
เพราะช่องส่วนใหญ่กำหนดขนาดด้วย text-xs/text-[11px] ที่ specificity สูงกว่า)
|
||||
responsive audit 2026-09-24: ครอบ contentEditable ของ TEXTBOX editor ด้วย —
|
||||
fontSize default 2.5% ≈ 15px ทำ Safari ซูม viewport ตอนแตะเข้าโหมดแก้ไข
|
||||
(ตัวอักษรขยายเป็น 16px เฉพาะช่วงพิมพ์ ต่างจากผลลัพธ์ ~7% — trade-off มาตรฐาน
|
||||
ของ editor บน iOS เพราะ maximum-scale กัน focus-zoom ไม่ได้) */
|
||||
input,
|
||||
textarea,
|
||||
select,
|
||||
[contenteditable]:not([contenteditable="false"]) {
|
||||
font-size: 1rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* UX review M7 2026-09-23: ปุ่มหลักของหน้ารายการ/กลุ่ม (Annotate h-8, ลิงก์กลุ่ม,
|
||||
ออกจากระบบ) สูง 32px ต่ำกว่ามาตรฐาน touch 44px ที่ viewer/หน้าสรุปได้แล้ว —
|
||||
หน้าที่ผู้ใช้ iPad แตะบ่อยที่สุดก่อนเปิดเอกสารต้องได้เป้าเท่ากัน (ครอบ a/button
|
||||
ของ <main class="listing-page"> + header ของ AppNav; select/summary เป็น
|
||||
native control/มี flex อยู่แล้ว ใส่แค่ min-height)
|
||||
ครอบด้วย @layer components ให้ Tailwind utilities (flex/items-*) ทับได้ —
|
||||
กฎ unlayered ชนะทุก layer จนบังคับ align-items:center ทับ items-start ของ
|
||||
แถวลิงก์ในการ์ดกลุ่ม กลายเป็นไอคอนลอยกลางแถว 2–3 บรรทัด (code review 2026-09-23)
|
||||
+ justify-content:center คืนค่า default ของปุ่ม (text-align:center ของ UA
|
||||
หมดผลเมื่อเป็น flex) ไม่งั้นปุ่ม w-full เช่น "เปิดเอกสาร"/อัปโหลด ข้อความชิดซ้าย
|
||||
(คำขอผู้ใช้ 2026-09-23)
|
||||
responsive audit 2026-09-24: @layer ต้องครอบ @media จากด้านนอกเท่านั้น — ซ้อนกลับกัน
|
||||
(@media { @layer {…} }) แล้ว Tailwind v3 ยกเนื้อหา @layer ออกไปวางที่ components
|
||||
section โดยทิ้ง media wrapper กฎจึงหลุดไป apply บน desktop ด้วย (ยืนยันด้วยการ
|
||||
build จริง: ปุ่มหน้ารายการได้ min-height 44px + flex บนจอ desktop) */
|
||||
@layer components {
|
||||
@media (pointer: coarse) {
|
||||
main.listing-page a,
|
||||
main.listing-page button {
|
||||
min-height: 2.75rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
main.listing-page select,
|
||||
main.listing-page summary {
|
||||
min-height: 2.75rem;
|
||||
}
|
||||
header.appnav a,
|
||||
header.appnav button {
|
||||
min-height: 2.75rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ─── Print (หน้าสรุป) — design review 2026-09-17 L4 ───────────────────────
|
||||
|
|
@ -249,16 +323,18 @@
|
|||
}
|
||||
}
|
||||
|
||||
/* UX review 2026-09-14 H2 → typography audit 2026-09-16 (T1 + Option B): webfont
|
||||
Sarabun (next/font จาก layout.tsx — variable มี adjusted fallback ของ next/font
|
||||
ในตัวแล้ว) นำหน้า stack เพื่อแสดงผลเหมือนกันทุกอุปกรณ์; ที่เหลือเป็น fallback
|
||||
ตอนฟอนต์ยังไม่ถึง (display:swap)/โหลดไม่ได้ — เรียงแบบ Latin-first ตาม T1:
|
||||
Latin/ตัวเลขได้ UI font ของ OS (Segoe UI/SF) ส่วนไทยได้ Leelawadee UI
|
||||
(Windows) / Thonburi (iPad) / Noto Sans Thai (Android/Linux) */
|
||||
/* UX review 2026-09-14 H2 → typography audit 2026-09-16 (T1 + Option B) →
|
||||
Genesis 2026-09-23: DM Sans (next/font ตัวแปร Latin) นำหน้า stack ให้ตัว
|
||||
Latin/ตัวเลขได้บุคลิก body ของ design system ก่อน จากนั้น webfont Sarabun
|
||||
(next/font — มี adjusted fallback ของ next/font ในตัว) รับ glyph ไทยโดยเฉพาะ
|
||||
แสดงผลเหมือนกันทุกอุปกรณ์; ที่เหลือเป็น fallback ตอนฟอนต์ยังไม่ถึง
|
||||
(display:swap)/โหลดไม่ได้ — ไทยได้ Leelawadee UI (Windows) / Thonburi (iPad)
|
||||
/ Noto Sans Thai (Android/Linux) / heading ใช้คลาส font-display ที่นำ
|
||||
General Sans มาก่อน Sarabun ด้วยหลักการเดียวกัน */
|
||||
body {
|
||||
font-family: var(--font-sarabun, "Sarabun"), -apple-system, "Segoe UI",
|
||||
"Helvetica Neue", Arial, "Leelawadee UI", "Thonburi", "Noto Sans Thai",
|
||||
sans-serif;
|
||||
font-family: var(--font-dm-sans, "DM Sans"), var(--font-sarabun, "Sarabun"),
|
||||
-apple-system, "Segoe UI", "Helvetica Neue", Arial, "Leelawadee UI",
|
||||
"Thonburi", "Noto Sans Thai", sans-serif;
|
||||
}
|
||||
|
||||
/* M6: touch hygiene — ตัดแถบเทากระพริบของ iOS ทุกครั้งที่แตะปุ่ม และกัน
|
||||
|
|
@ -306,12 +382,13 @@ html {
|
|||
}
|
||||
|
||||
/* เส้นคั่นบางระหว่างแถวตั้งค่า (PanelRow) ที่ต่อกันในเมนู tool/แผง selection —
|
||||
ระยะ/เส้นเท่ากับแทรก <div class="my-1.5 border-t border-slate-100"> ไว้ระหว่างแถว
|
||||
ทุกจุด (แถวแรกของกลุ่มไม่มีเส้น — ไม่ซ้ำกับ divider ที่เมนูใส่ไว้เองแล้ว) */
|
||||
ระยะ/เส้นเท่ากับแทรก <div class="my-1.5 border-t border-line"> ไว้ระหว่างแถว
|
||||
ทุกจุด (แถวแรกของกลุ่มไม่มีเส้น — ไม่ซ้ำกับ divider ที่เมนูใส่ไว้เองแล้ว)
|
||||
(#E8E8EC = token line — เดิม #f1f5f9 เป็น slate-100 หลงเหลือก่อน Genesis) */
|
||||
.panel-row + .panel-row {
|
||||
margin-top: 0.375rem;
|
||||
padding-top: 0.625rem;
|
||||
border-top: 1px solid #f1f5f9;
|
||||
border-top: 1px solid #e8e8ec;
|
||||
}
|
||||
|
||||
/* M6: safe-area — defensive (ค่าเป็น 0 จนกว่าจะใส่ viewport-fit=cover ใน meta
|
||||
|
|
@ -325,7 +402,9 @@ header {
|
|||
|
||||
/* UX audit 2026-09-16 L7: เคารพ prefers-reduced-motion — ตัด transition ของ
|
||||
sidebar, animation กระพริบของปุ่ม export และ smooth scroll ทุกจุด
|
||||
(scrollToBelowHeader ฝั่ง JS เช็ค media query เดียวกันตอนเลือก behavior) */
|
||||
(scrollToBelowHeader ฝั่ง JS เช็ค media query เดียวกันตอนเลือก behavior)
|
||||
UX review m7 2026-09-23: เพิ่ม blanket rule ครอบ transition/animation ที่เหลือ
|
||||
(hover-lift ของการ์ด, scale ของสวอตช์สี ฯลฯ) — ยก motion ทั้งหน้าให้จบทันที */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
aside[data-sidebar] {
|
||||
transition: none;
|
||||
|
|
@ -333,7 +412,12 @@ header {
|
|||
.animate-pulse {
|
||||
animation: none;
|
||||
}
|
||||
* {
|
||||
*,
|
||||
::before,
|
||||
::after {
|
||||
transition-duration: 0.01ms !important;
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue