UX audit ทั้งแอป + typography audit 2026-09-16: toast แจ้ง error การบันทึก (H1 — เดิมรายการหายเงียบ + ReplyBox เก็บ draft ตอน fail), คำเตือน redaction แสดงทุกขนาดจอ (H2), toolbar แสดงชื่อ tool active + aria-pressed บนจอสัมผัส (H3/M9), ปุ่ม popover จิ้มง่าย 36px + focus ring เติมครบ (H4) + M1-M9 (ปิด sidebar ตอน navigate, bookmark หัวแถวจอเล็ก, hint โหมดมาร์กบนจอสัมผัส, การ์ดหน้ารายการคลิกได้ทั้งใบ, เช็ค 100MB ฝั่ง client, feedback ✓/pending ตอนบันทึก bookmark, dropdown วางที่ sort ตามหน้า+เลขหน้า, slate-500 แทน slate-400) + webfont Sarabun ผ่าน next/font self-host 400/600 (Option B — แสดงผลตรงกันทุกอุปกรณ์ รวม TEXTBOX ที่ผูก stack นี้) + NumberCombo preset เป็น chips แทน dropdown ล้นเมนู (L2) + leading-relaxed/13px ข้อความไทยที่ wrap + tabular-nums + prefers-reduced-motion (L7) + L1/L4/L5 + แถว bookmark แสดงชื่อผู้บันทึกเหมือนผลการค้นหา
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
parent
a020e96bda
commit
21b9958600
10 changed files with 351 additions and 158 deletions
|
|
@ -84,17 +84,17 @@ export default async function SummaryPage({
|
|||
<span className="block text-xs">
|
||||
<span className="font-medium">{annotationTypeLabel(a)}</span>
|
||||
{a.type === "COMMENT" && a.resolved && (
|
||||
<span className="ml-2 rounded bg-emerald-50 px-1.5 py-0.5 text-[10px] text-emerald-600">
|
||||
<span className="ml-2 rounded bg-emerald-50 px-1.5 py-0.5 text-[11px] text-emerald-600">
|
||||
จัดการแล้ว
|
||||
</span>
|
||||
)}
|
||||
<span className="ml-2 text-slate-400">{a.userName}</span>
|
||||
</span>
|
||||
<span className="mt-0.5 block whitespace-pre-wrap break-words text-sm">
|
||||
<span className="mt-0.5 block whitespace-pre-wrap break-words text-sm leading-relaxed">
|
||||
{annotationPreviewText(a)}
|
||||
</span>
|
||||
{annotationNote(a) && (
|
||||
<span className="mt-0.5 block whitespace-pre-wrap break-words text-xs text-slate-500">
|
||||
<span className="mt-0.5 block whitespace-pre-wrap break-words text-xs leading-relaxed text-slate-500">
|
||||
โน้ต: {annotationNote(a)}
|
||||
</span>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -108,10 +108,11 @@
|
|||
|
||||
/* NumberCombo (ความหนา/ความทึบ/ขนาด): ▲▼ ซ้อนแนวตั้ง 2 ปุ่ม — ถ้าโดน min 36px
|
||||
คอลัมน์จะสูง 72px และ input (items-stretch) ถูกดึงบวมตามทั้งแถว — ปุ่ม ▲▼
|
||||
จึงหลุดจาก rule ด้านบน (combo-step) แล้วตั้งความสูงแถวเองที่ 36px แทน:
|
||||
แตะ input = เปิด preset list (แถวละ 36px จาก rule ด้านบน) คือ touch path
|
||||
หลัก ส่วน ▲▼ (ครึ่งแถว) เป็น fine-tune สำรอง — ขนาดใกล้ desktop ไม่บวม */
|
||||
[data-tool-menu] .number-combo > div {
|
||||
จึงหลุดจาก rule ด้านบน (combo-step) แล้วตั้งความสูงแถว input เองที่ 36px
|
||||
แทน (:first-child — แถว chips preset ของ L2 โดน rule ปุ่ม 36px ของเมนู
|
||||
ครอบอยู่แล้ว ห้ามบังคับสูงซ้ำ): แตะ chips preset = touch path หลัก
|
||||
ส่วน ▲▼ (ครึ่งแถว) เป็น fine-tune สำรอง — ขนาดใกล้ desktop ไม่บวม */
|
||||
[data-tool-menu] .number-combo > div:first-child {
|
||||
height: 2.25rem;
|
||||
}
|
||||
[data-tool-menu] .combo-step {
|
||||
|
|
@ -197,14 +198,16 @@
|
|||
}
|
||||
}
|
||||
|
||||
/* UX review 2026-09-14 H2: แอปไม่เคยตั้ง font-family เลย ข้อความไทยเลยตกไปที่
|
||||
default ของ OS แต่ละเครื่อง — วางฟอนต์ไทยนำหน้า stack (ไม่โหลด webfont
|
||||
ตามที่เลือกไว้: Leelawadee UI = Windows, Noto Sans Thai = Android/Linux,
|
||||
Thonburi = macOS) */
|
||||
/* 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) */
|
||||
body {
|
||||
font-family: "Leelawadee UI", "Noto Sans Thai", "Thonburi",
|
||||
ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
|
||||
"Helvetica Neue", Arial, sans-serif;
|
||||
font-family: var(--font-sarabun, "Sarabun"), -apple-system, "Segoe UI",
|
||||
"Helvetica Neue", Arial, "Leelawadee UI", "Thonburi", "Noto Sans Thai",
|
||||
sans-serif;
|
||||
}
|
||||
|
||||
/* M6: touch hygiene — ตัดแถบเทากระพริบของ iOS ทุกครั้งที่แตะปุ่ม และกัน
|
||||
|
|
@ -249,3 +252,18 @@ header {
|
|||
.comment-composer {
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
|
||||
/* UX audit 2026-09-16 L7: เคารพ prefers-reduced-motion — ตัด transition ของ
|
||||
sidebar, animation กระพริบของปุ่ม export และ smooth scroll ทุกจุด
|
||||
(scrollToBelowHeader ฝั่ง JS เช็ค media query เดียวกันตอนเลือก behavior) */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
aside[data-sidebar] {
|
||||
transition: none;
|
||||
}
|
||||
.animate-pulse {
|
||||
animation: none;
|
||||
}
|
||||
* {
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,21 @@
|
|||
import type { Metadata } from "next";
|
||||
import { Sarabun } from "next/font/google";
|
||||
|
||||
import "./globals.css";
|
||||
|
||||
/** typography audit 2026-09-16 (Option B): Sarabun — ฟอนต์ตระกูลมาตรฐานเอกสาร
|
||||
* ราชการไทย (TH Sarabun) เจ้าหน้าที่คุ้นเคยที่สุด / next/font self-host ตอน build:
|
||||
* ไฟล์ฟอนต์ serve จาก origin เดียวกับแอป ไม่พึ่ง Google ตอนรัน จึงใช้ใน intranet
|
||||
* ได้ (แต่เครื่อง build ต้องเห็นอินเทอร์เน็ต) — โหลดเฉพาะ 2 weights ตามแผน
|
||||
* ~100-160KB แลกกับการแสดงผลเหมือนกันทุกอุปกรณ์ รวมกล่อง TEXTBOX ที่ผูก
|
||||
* stack นี้ (T1-C: wrap ข้อความตรงกันข้ามอุปกรณ์จริง) */
|
||||
const sarabun = Sarabun({
|
||||
subsets: ["thai", "latin"],
|
||||
weight: ["400", "600"],
|
||||
display: "swap",
|
||||
variable: "--font-sarabun",
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Judge's Note",
|
||||
description: "ระบบ PDF Annotation สำหรับ e-Court",
|
||||
|
|
@ -13,7 +27,7 @@ export default function RootLayout({
|
|||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<html lang="th">
|
||||
<html lang="th" className={sarabun.variable}>
|
||||
<body className="bg-slate-100 text-slate-900 antialiased">{children}</body>
|
||||
</html>
|
||||
);
|
||||
|
|
|
|||
20
app/page.tsx
20
app/page.tsx
|
|
@ -1,6 +1,6 @@
|
|||
import Link from "next/link";
|
||||
import { asc } from "drizzle-orm";
|
||||
import { FileImage, FileText } from "lucide-react";
|
||||
import { ChevronRight, FileImage, FileText } from "lucide-react";
|
||||
|
||||
import { db } from "@/db";
|
||||
import { files } from "@/db/schema";
|
||||
|
|
@ -48,7 +48,7 @@ export default async function HomePage() {
|
|||
<div className="mt-8 flex items-baseline justify-between">
|
||||
<h2 className="text-sm font-semibold text-slate-700">เอกสาร</h2>
|
||||
{rows.length > 0 && (
|
||||
<span className="text-xs text-slate-400">{rows.length} ไฟล์</span>
|
||||
<span className="text-xs tabular-nums text-slate-500">{rows.length} ไฟล์</span>
|
||||
)}
|
||||
</div>
|
||||
<UploadFileForm />
|
||||
|
|
@ -59,7 +59,7 @@ export default async function HomePage() {
|
|||
<p className="mt-3 text-sm font-medium text-slate-500">
|
||||
ยังไม่มีไฟล์ในระบบ
|
||||
</p>
|
||||
<p className="mt-1 text-xs text-slate-400">
|
||||
<p className="mt-1 text-xs text-slate-500">
|
||||
รัน /sync-db เพื่อ seed ไฟล์ตัวอย่าง
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -68,7 +68,7 @@ export default async function HomePage() {
|
|||
{rows.map((f) => (
|
||||
<li
|
||||
key={f.id}
|
||||
className="group flex items-center gap-3 rounded-xl border border-slate-200 bg-white p-4 shadow-sm transition hover:border-primary/30 hover:shadow-md"
|
||||
className="group relative flex items-center gap-3 rounded-xl border border-slate-200 bg-white p-4 shadow-sm transition hover:border-primary/30 hover:shadow-md"
|
||||
>
|
||||
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary/10">
|
||||
{imageFormatFromUrl(f.pdfUrl) ? (
|
||||
|
|
@ -81,19 +81,21 @@ export default async function HomePage() {
|
|||
<span className="block break-all line-clamp-2 text-sm font-medium text-slate-900">
|
||||
{f.title}
|
||||
</span>
|
||||
<span className="mt-0.5 block text-xs text-slate-400">
|
||||
<span className="mt-0.5 block text-xs text-slate-500">
|
||||
<span className="mr-1.5 rounded bg-slate-100 px-1 py-0.5 font-medium text-slate-500">
|
||||
{kindBadge(f.pdfUrl)}
|
||||
</span>
|
||||
{new Date(f.createdAt).toLocaleString("th-TH")}
|
||||
</span>
|
||||
</span>
|
||||
<ChevronRight aria-hidden className="h-4 w-4 shrink-0 text-slate-400" />
|
||||
{/* M4 (UX audit 2026-09-16): ลิงก์กางเต็มการ์ด — จอสัมผัสจิ้มตรงไหนก็เข้าได้
|
||||
(เดิมปุ่ม "Annotate" ~30px อย่างเดียว และเป็นภาษาอังกฤษใน UI ไทย) */}
|
||||
<Link
|
||||
href={`/annotate/${f.id}`}
|
||||
className="shrink-0 rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-white transition hover:opacity-90"
|
||||
>
|
||||
Annotate
|
||||
</Link>
|
||||
className="absolute inset-0 rounded-xl focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-1"
|
||||
aria-label={`เปิด ${f.title}`}
|
||||
/>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue