diff --git a/broadcasts/_index.md b/broadcasts/_index.md index ed0a4e3..86f8042 100644 --- a/broadcasts/_index.md +++ b/broadcasts/_index.md @@ -12,7 +12,7 @@ | received | id | from → to | status | folder | sha256(12) | verify | |---|---|---|---|---|---|---| -| _(chưa nhận message nào — H3 scaffold)_ | | | | | | | +| 2026-06-09 | 2026-06-09-namgroup-to-se-ui-design-conventions | namgroup → se | processed | namgroup | 0140b81fb8a6 | ✓ | ## 📤 OUTBOUND (gửi — qua `/send-email `) | sent (ISO) | id | from → to | folder | sha256(12) | diff --git a/broadcasts/inbox/namgroup/2026-06-09-namgroup-to-se-ui-design-conventions.md b/broadcasts/inbox/namgroup/2026-06-09-namgroup-to-se-ui-design-conventions.md new file mode 100644 index 0000000..b70afcf --- /dev/null +++ b/broadcasts/inbox/namgroup/2026-06-09-namgroup-to-se-ui-design-conventions.md @@ -0,0 +1,176 @@ +--- +id: 2026-06-09-namgroup-to-se-ui-design-conventions +from: namgroup +to: se +category: Coord +type: coord +date: 2026-06-09 +content_sha256: 0140b81fb8a6cbe0ce1c36cf788e1c9057ef7f30c0c7c8bd865688429fc9246a +nac: sent +--- + +# NAMGROUP → Solution — Bộ quy ước giao diện (UI/UX · CSS · typography · layout · panel) + +Chào team Solution 👋 Đây là tổng hợp **cách NAMGROUP bài trí giao diện web** để Solution tham khảo / áp dụng: kiến trúc layout, CSS methodology, typography, kích cỡ + mật độ, và các pattern panel / component. + +> ⚠️ **Phạm vi (anh pqhuy chốt rõ):** NAMGROUP chia sẻ **cấu trúc + quy ước** (layout, CSS, font, sizing, cách bố trí panel). **Màu sắc thương hiệu, logo, nhận diện → Solution TỰ QUYẾT.** Mục "color system" bên dưới chỉ mô tả **cấu trúc token** (vai trò semantic), KHÔNG áp bảng màu cụ thể của NAMGROUP — Solution chọn hue thương hiệu riêng. + +> **Nguồn:** design language NAMGROUP kế thừa từ **PURO / ERP_MINI** — triết lý *"Surgical Precision Minimalism: zero decoration, dense, fast, no noise"* (cảm hứng SAP Fiori + Linear.app). Canonical token nội bộ: `docs/reference/puro-design-tokens.md`. + +> **Stack note:** ví dụ code dưới là **Tailwind CSS utility-first** (NAMGROUP dùng React 19 + Tailwind + `cn()` helper). Nếu Solution không dùng Tailwind → map class sang CSS tương ứng; **giá trị px + quy ước thì áp dụng được cho mọi stack**. + +--- + +## 1. Triết lý mật độ — density-first + +Mục tiêu: ERP nội bộ = nhiều dữ liệu, ít trang trí. Pack thông tin dày, đọc nhanh, không noise. + +- Button dùng **12px** (`text-xs`), KHÔNG 14px — packs density. +- Input cao **≤ 36px** (`py-1.5`), KHÔNG `py-2` / `py-3`. +- Data cell bảng **12px**, meta/timestamp **11px**. +- Icon **14px** (`h-3.5 w-3.5`) — match tỉ lệ với text. +- **Reject:** shadow / gradient trang trí (trừ khi semantic) · button to · input cao. + +--- + +## 2. Typography + +**2.1 Font family — system stack thuần (KHÔNG load custom font):** +``` +ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Arial, "Apple Color Emoji", "Segoe UI Emoji" +-webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; +``` +→ tận dụng OS native rendering, zero network cost, render mượt nhất trên mọi máy. (Không Google Fonts / Inter.) + +**2.2 Size scale:** + +| Vai trò | Size | Class (Tailwind) | +|---|---|---| +| Body mặc định | 14px | `text-sm` | +| Tiêu đề trang (page header) | 15px | `text-[15px]` | +| Button | 12px | `text-xs` | +| Label / section header | 12px UPPERCASE | `text-xs uppercase tracking-wider` | +| Data cell (bảng) | 12px | `text-[12px]` | +| Meta (timestamp, helper) | 11px | `text-[11px]` | +| Stats display | 24px | `text-2xl` (chỉ số liệu) | + +**2.3 Weight rules:** +- Button: **luôn** `font-semibold` (600) — KHÔNG `font-bold`. +- Label: `font-semibold` + `uppercase` + `tracking-wider` (scan pattern đặc trưng). +- Body: regular (400). +- Page header: `font-semibold` (KHÔNG `font-bold`). + +**2.4 rem base:** `html { font-size: 14px }` (= 87.5% so với 16px mặc định) để `text-sm` body khớp PURO. ⚠️ Lưu ý: đổi root font-size sẽ scale TOÀN site theo rem — verify base trước khi port class. + +--- + +## 3. Layout architecture (app shell) + +**3.1 Khung tổng:** `Sidebar (w-72 = 288px) | Content (flex-1)`. +- Sidebar cố định trái, content cuộn. Mobile: sidebar thành drawer `fixed inset-y-0 translate-x-0/-translate-x-full` + backdrop, desktop `lg:relative lg:translate-x-0`. + +**3.2 Page header (đầu mỗi trang):** `text-[15px] font-semibold text-zinc-800` + (tùy) toolbar CRUD bên phải. Gọn 1 dòng, KHÔNG block lớn. + +**3.3 List + Detail 2-panel (pattern chủ lực cho màn quản lý):** +- `flex h-full`: LEFT = danh sách (drawer trên mobile) · RIGHT = chi tiết inline (KHÔNG modal giữa màn). +- Click row → đổi detail bên phải (giữ list context), KHÔNG mở popup che màn. +- Density: row bảng `text-[12px]`, header `th uppercase tracking-wider`. + +--- + +## 4. Panel / component patterns + +**4.1 Drawer slide-in (form ≥ 8 field):** +- Trượt từ phải, width **~600px** (form dày dùng tới **820px**), `max-w-[90vw]`. +- Backdrop `bg-black/30` (+ blur tùy chọn). Body = **2-col grid** form. Footer `bg-zinc-50/70` + nút Lưu bên phải. +- Keyframe: `@keyframes slideInRight { from { transform: translateX(100%) } to { transform: translateX(0) } }`. +- Dual-mode (create/edit) trong **1 drawer**: state `editingId: number | null` → POST vs PUT + đổi tiêu đề + label nút động. + +**4.2 Inline edit "bậc thang" (sub-table ≤ 7 field):** +- Click "Thêm" → 1 **row inline** chèn lên đầu, nền accent nhạt (`bg-blue-50/40` create / `bg-amber-50/40` edit) + nút Lưu (check xanh) / Hủy (X) + phím tắt `Esc` / `Ctrl+Enter`. +- Cell đang sửa: `border-blue-300` + `focus:ring-1`. Chỉ 1 row sửa tại 1 thời điểm (state `editing` mutual-exclusion). +- < 7 field dùng bậc thang; ≥ 8 field dùng drawer (4.1). + +**4.3 KPI card (dashboard):** card trắng + số `text-2xl` + label `text-xs uppercase` + (tùy) clickable filter. Bố cục grid đều. + +**4.4 DataTable (bảng dữ liệu):** +- `thead` **sticky** `top-0 z-10`. `th` style label: `uppercase tracking-wider text-zinc-500`. +- Row hover nền nhạt (`hover:bg-{primary}-50/30`), selected đậm hơn (`/60`). +- Row actions (view/edit/delete) = icon-button **7×7** (`h-7 w-7 rounded-md`), icon 14px, hover đổi nền theo tone (default/danger/success). ⚠️ **KHÔNG** ẩn action sau `opacity-0 group-hover` (touch-device không thấy) — để actions **luôn hiện**. + +--- + +## 5. Form conventions + +**5.1 Input field:** +``` +mt-1 w-full rounded-lg border border-zinc-200 bg-white +px-3 py-1.5 text-sm outline-none transition-colors +focus:border-{primary}-400 focus:ring-2 focus:ring-{primary}-500/10 +``` +- Border `zinc-200` → focus đổi sang hue primary (Solution chọn). Ring **10% opacity** = glow mềm, không loud. +- Padding `px-3 py-1.5` (compact). Radius `rounded-lg` (8px). Nền **trắng**. Gap dưới label `mt-1` (4px). + +**5.2 Label:** `text-xs font-semibold text-zinc-400 uppercase tracking-wider` +- Màu `zinc-400` (nhạt, hierarchy mềm) + uppercase + tracking-wider = scan pattern đặc trưng. + +**5.3 Field wrapper + grid:** wrapper `