---
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)
