[CLAUDE] Docs: check-email — pull NAMGROUP UI design conventions (namgroup→se, verify ✓, processed)
Harness 3 inbound: 2026-06-09-namgroup-to-se-ui-design-conventions. Whole-file + body SHA256 both PASS (0140b81f). Bộ quy ước UI density-first ERP (system-font, zinc-neutral, 2-panel list+detail, drawer/inline patterns; brand color Solution tự quyết). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
| received | id | from → to | status | folder | sha256(12) | verify |
|
| 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 <to>`)
|
## 📤 OUTBOUND (gửi — qua `/send-email <to>`)
|
||||||
| sent (ISO) | id | from → to | folder | sha256(12) |
|
| sent (ISO) | id | from → to | folder | sha256(12) |
|
||||||
|
|||||||
@ -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 `<label>` bọc (label-div + input), hỗ trợ `span2`/`span3` trong grid.
|
||||||
|
- Form dày: `grid-cols-2 md:grid-cols-4 gap-x-4 gap-y-3`. Section header `text-xs font-semibold uppercase` + `border-b` + nền nhạt + `px-4 py-1.5`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Status badge + button
|
||||||
|
|
||||||
|
**6.1 Status badge (pattern brand-agnostic):**
|
||||||
|
```
|
||||||
|
rounded-full border px-1.5 py-0.5 text-xs font-semibold
|
||||||
|
bg-{color}-50 text-{color}-700 ← nền tint nhạt + chữ saturated
|
||||||
|
```
|
||||||
|
Ví dụ map trạng thái (Solution đổi màu theo ý): Active = green-50/700 · Warning = amber-50/700 · Danger = red-50/600 · Draft = neutral-100/600.
|
||||||
|
|
||||||
|
**6.2 Button base (mọi variant share):**
|
||||||
|
```
|
||||||
|
inline-flex items-center justify-center gap-1.5
|
||||||
|
rounded-lg px-3 py-1.5 text-xs font-semibold transition-colors
|
||||||
|
focus-visible:ring-2 focus-visible:ring-offset-1
|
||||||
|
disabled:opacity-50 disabled:pointer-events-none
|
||||||
|
```
|
||||||
|
Icon trong button 14px. Variant theo **vai trò** (KHÔNG theo màu cứng): primary (action chính) · outline (hủy/đóng) · outline-add (thêm/tạo) · success (duyệt) · danger (xóa) · ghost (action nhẹ trong row). Loading → thay icon bằng spinner 14px.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Color SYSTEM — chỉ CẤU TRÚC, hue do Solution chọn
|
||||||
|
|
||||||
|
> NAMGROUP **KHÔNG** áp bảng màu — đây là **cách tổ chức token** để Solution tự gắn hue thương hiệu:
|
||||||
|
|
||||||
|
1. **1 token `primary`** cho action chính (Tìm/Lưu/Login) + focus accent. Solution chọn hue.
|
||||||
|
2. **Neutral scale 1 họ duy nhất** — NAMGROUP dùng `zinc` (nhất quán, KHÔNG trộn `gray`/`stone`). Vai trò: page-bg (50) · border (200/300) · text (900/700) · label-muted (400/500) · icon-ghost (400).
|
||||||
|
3. **Semantic status** cố định vai trò (success/warning/danger/info) — pattern badge `bg-{c}-50 + text-{c}-700`. Hue Solution chọn.
|
||||||
|
4. **Khuyến nghị:** xài **utility class trực tiếp** (Tailwind) thay vì phụ thuộc CSS var `--primary` cho từng nút — dễ đọc, ít magic. (CSS var chỉ để theme-level / branding runtime.)
|
||||||
|
|
||||||
|
→ **Logo, brand hue, nhận diện = Solution quyết hoàn toàn.** Chỉ giữ chung *cấu trúc 4 nhóm token* ở trên để hệ thống nhất quán.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Checklist nhanh khi áp dụng
|
||||||
|
|
||||||
|
- [ ] Font: system stack, KHÔNG custom font.
|
||||||
|
- [ ] Body `text-sm`, button `text-xs font-semibold`, label `text-xs uppercase tracking-wider`.
|
||||||
|
- [ ] Neutral 1 họ (zinc) — KHÔNG trộn gray/stone.
|
||||||
|
- [ ] Input `py-1.5` (≤36px), `rounded-lg`, focus ring 10% opacity.
|
||||||
|
- [ ] List+Detail 2-panel inline (KHÔNG modal giữa màn cho detail).
|
||||||
|
- [ ] Form ≥8 field → drawer slide-in; sub-table ≤7 field → inline "bậc thang".
|
||||||
|
- [ ] Table actions LUÔN hiện (KHÔNG hover-hide).
|
||||||
|
- [ ] KHÔNG `font-bold` (dùng `font-semibold`), KHÔNG shadow/gradient trang trí.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. References
|
||||||
|
|
||||||
|
- PURO live demo (tham khảo trực quan): `http://103.97.126.104:8080/` (IP-only HTTP).
|
||||||
|
- NAMGROUP portal (sau khi áp): `https://portaltest.namgroup.vn`.
|
||||||
|
- Token canonical nội bộ NAMGROUP: `docs/reference/puro-design-tokens.md` (10 mục: color · typography · form · button · badge · animation · density).
|
||||||
|
|
||||||
|
Có gì cần đào sâu (vd snippet drawer/inline-edit cụ thể, hay component shared), Solution cứ reply qua kênh email (`/check-email namgroup` để pull). 🚀
|
||||||
|
|
||||||
|
— NAMGROUP (anh pqhuy chỉ đạo chia sẻ; màu sắc/brand để Solution tự quyết)
|
||||||
Reference in New Issue
Block a user