Files
sys-analysis-design/.claude/skills/ba-design/templates/design-system.md
2026-09-11 23:01:18 +07:00

197 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# DS — Design System — <PROJECT>
| | |
|---|---|
| **Version** | 1.0 |
| **Date** | YYYY-MM-DD |
| **Author** | <BA/Design> (skill ba-design, activity `ds`) |
| **Status** | 🟡 Draft |
| **Approved by** | Designer: — · PO: — |
| **Source** | UICONV_<PROJECT> v1.0 · brand guideline: <đường dẫn / "chưa có — OQ-nnn"> · design system tham chiếu: <tên + version / "chưa có"> · SAD §7 (nếu có) |
| **Scope** | Toàn project — mọi `HIFI`, `FIGMA`, `DSPEC` có `PRODUCT = screen` |
| **Profile** | `screen · … · …` |
| **Tệp kèm** | `00-index/ds/tokens.json` (nguồn sự thật) · `ds/tokens.css` (sinh từ json) · `ds/components.html` (component sheet, mở bằng trình duyệt) |
## Change Log
| Version | Date | Người sửa | Thay đổi | CR |
|---|---|---|---|---|
| 1.0 | | | Bản đầu | — |
> **Vai trò của tài liệu này.** `UICONV` nói *hành xử thế nào* (phân trang, vị trí toast, validate lúc nào);
> tài liệu này nói *trông thế nào* (màu, chữ, khoảng cách, bo góc, đổ bóng, trạng thái hover/focus/disabled).
> `HIFI` và `FIGMA` chỉ dùng token và component ở đây; muốn khác phải có dòng ở §8.
>
> **Thứ tự ưu tiên khi lệch:** Brand guideline của khách > Design system tham chiếu (nếu dự án đã chọn) >
> `DS` này > `HIFI` từng US. Thiếu brand ⇒ giá trị ở đây là **đề xuất trung tính** chờ Designer/PO chốt — ghi `OQ`, không tự coi là đã duyệt.
---
## 0. Nguồn và độ tin cậy
| | |
|---|---|
| **Brand guideline** | *(file/URL + version, hoặc "Chưa có" ⇒ mọi giá trị màu/chữ ở §1 là placeholder trung tính, `OQ-nnn`)* |
| **Design system tham chiếu** | *(Material 3 / Ant Design / nội bộ… + version — theo `OQ` ở UICONV §0 hoặc quyết định của Tech Lead `DEC-nn`)* |
| **Prototype đã có** | *(Figma / HTML / SAD §7 — token được trích từ đây nếu có)* |
| **Ai sở hữu** | BA/Design đề xuất · **Designer duyệt** visual · PO duyệt giọng văn/nhận diện · Dev FE xác nhận khả năng hiện thực với stack đã chọn |
| **Độ tin cậy** | 🟢 Trích từ brand/DS thật · 🟡 Suy từ prototype · 🔴 Đề xuất trung tính, chưa có nguồn — *(chọn một, ghi lý do)* |
## 1. Token
*Bảng này tóm tắt; giá trị chuẩn ở `ds/tokens.json`. Sửa ⇒ sửa json, sinh lại css, chạy `design-check.mjs`.*
### 1.1 Màu
| Token | Giá trị | Dùng cho | Nguồn |
|---|---|---|---|
| `color.bg.canvas` | | Nền trang | |
| `color.bg.surface` | | Card, bảng, modal | |
| `color.bg.subtle` | | Header bảng, vùng phụ | |
| `color.border.default` / `.strong` | | Viền chia / viền ô nhập | |
| `color.text.primary` / `.secondary` / `.disabled` / `.inverse` | | Chữ chính / phụ / vô hiệu / trên nền đậm | |
| `color.brand.primary` / `-hover` / `-subtle` | | Nút chính, liên kết, focus / hover / nền chọn | |
| `color.status.danger` / `success` / `warning` (+ `-subtle`) | | Lỗi / thành công / cảnh báo | |
### 1.2 Chữ
| Token | Giá trị | Dùng cho |
|---|---|---|
| `font.family.base` | | Toàn hệ thống — *(font brand hay system stack? nguồn)* |
| `font.size.xs / sm / md / lg / xl / 2xl` | 12 / 14 / 16 / 20 / 24 / 32 px | Hint, nhãn / body / nhãn field lớn, h3 / h2 / h1 / số KPI |
| `font.weight.regular / semibold` | 400 / 600 | |
| `font.line-height.tight / normal` | 1.25 / 1.5 | Tiêu đề / body |
### 1.3 Khoảng cách, bo góc, đổ bóng, kích thước
| Token | Giá trị | Ghi chú |
|---|---|---|
| `space.1 … 12` | 4 · 8 · 12 · 16 · 24 · 32 · 48 px | Thang 4px; không dùng số ngoài thang |
| `radius.sm / md / pill` | 4 / 8 / 999 px | Nút, ô nhập / card, modal / badge |
| `shadow.sm / md` | | Card nổi / modal, toast |
| `size.control.desktop / touch` | 36 / 44 px | Chiều cao nút, ô nhập; **mobile ≥ 44px** (hit target) |
| `size.icon` | 20 px | Icon inline |
| `size.content-max` | 1200 px | Khớp UICONV §1 max-width |
| `breakpoint.tablet / desktop` | 768 / 1024 px | **Phải khớp UICONV §1** |
## 2. Thang chữ áp dụng
| Cấp | Token size / weight / line-height | Dùng ở |
|---|---|---|
| H1 — tiêu đề màn hình | xl / semibold / tight | `C01` kiểu "Tiêu đề cấp 1" |
| H2 — tiêu đề vùng, modal | lg / semibold / tight | |
| H3 — tiêu đề card | md / semibold / tight | |
| Body | sm / regular / normal | Bảng, form, câu dẫn |
| Nhãn field, hint, header bảng | xs / semibold hoặc regular / normal | |
## 3. Từ vựng component — ánh xạ ba chiều
*Cột 1 = UICONV §11 (BA) · cột 2 = lớp CSS trong `ds/components.html` (HIFI dùng) · cột 3 = component của design system tham chiếu (Dev FE dùng). Mọi kiểu trình bày xuất hiện trong `WF` phải có dòng ở đây.*
| Kiểu trình bày (UICONV §11) | Lớp DS | Component DS tham chiếu | Ghi chú |
|---|---|---|---|
| Nút chính | `.ds-btn.ds-btn--primary` | | Một nút chính mỗi màn hình |
| Nút phụ | `.ds-btn.ds-btn--secondary` | | |
| Nút nguy hiểm | `.ds-btn.ds-btn--danger` | | Luôn kèm modal xác nhận |
| Liên kết | `.ds-link` | | |
| Ô nhập / Ô nhập số | `.ds-field` + `.ds-input` | | Nhãn trên field, `*` sau nhãn |
| Chọn 1 (≤7) / (>7) | `.ds-check` radio / `.ds-select` | | |
| Chọn nhiều | `.ds-check` checkbox | | |
| Công tắc | `.ds-switch` | | |
| Bộ đếm số lượng | `.ds-stepper` | | |
| Bảng / Card | `.ds-table-wrap` / `.ds-cards > .ds-card` | | Bảng desktop → card mobile (UICONV §3) |
| Badge trạng thái | `.ds-badge[--info/--success/--warning/--danger]` | | Ánh xạ trạng thái BR §3 → biến thể: *(bảng riêng bên dưới)* |
| Tab | `.ds-tabs > .ds-tab` | | |
| Modal / Drawer / Bottom-sheet | `.ds-modal-backdrop > .ds-modal` | | Nút chính bên phải |
| Toast | `.ds-toast[--error]` | | Vị trí, thời lượng theo UICONV §5 |
| Banner trong vùng | `.ds-banner[--error/--warning]` | | |
| Skeleton | `.ds-skeleton` | | |
| Trạng thái rỗng (2 loại) | `.ds-empty` (có minh hoạ) / `.ds-empty.ds-empty--filter` (không) | | 🔴 Hai loại phải trông khác nhau |
| Trang trạng thái | `.ds-status-page` | | 404 / 403 / lỗi toàn trang |
**Ánh xạ trạng thái nghiệp vụ → badge** *(từ `BR` §3 của từng module; bổ sung dần)*:
| Trạng thái (BR) | Biến thể badge | Nhãn nguyên văn (SRS §4.2) |
|---|---|---|
| | | |
## 4. Trạng thái component
*Mỗi ô ghi thay đổi thị giác (token nào đổi). "—" = không có trạng thái đó. Ô trống = chưa thiết kế.*
| Component | Default | Hover | Focus | Disabled | Loading | Error / Invalid | Selected |
|---|---|---|---|---|---|---|---|
| Nút chính | `brand.primary` | `brand.primary-hover` | ring 2px `focus.ring` | opacity .45 + **tooltip lý do** | spinner + nhãn "Đang …" | — | — |
| Nút phụ | surface + `border.strong` | `bg.subtle` | ring | opacity .45 + tooltip | spinner | — | — |
| Ô nhập | `border.strong` | `text.secondary` | `brand.primary` + ring | `bg.subtle`, chữ disabled | — | `status.danger` + message dưới | — |
| Dòng bảng | surface | `bg.canvas` | ring | — | skeleton | — | `brand.primary-subtle` |
| Tab | `text.secondary` | | ring | | | | `brand.primary` + gạch dưới 2px |
| Card | | | | | | | |
## 5. Icon
| | |
|---|---|
| **Bộ icon** | *(tên bộ + version / "inline SVG tự vẽ theo mẫu components.html")* |
| **Quy cách** | Lưới 24, stroke 1.75, `stroke-linecap: round`, hiển thị 20px (`size.icon`), màu `currentColor` |
| **Cấm** | Emoji, ký hiệu ✓✕▲ dạng chữ thay icon (trừ mũi tên phân trang `‹ ›`), icon tô đặc trộn với icon nét |
| **Danh sách dùng** | search · plus · close · chevron-down · back · check · alert · trash · filter · *(bổ sung theo WF)* |
## 6. Tương phản và khả năng truy cập
*Kết quả chạy `node scripts/design-check.mjs --tokens ds/tokens.json` — chép nguyên văn, không sửa tay.*
| Cặp (fg / bg) | Dùng cho | Tỷ lệ | Ngưỡng | ☐/✅ |
|---|---|---|---|---|
| `text.primary` / `bg.surface` | Chữ thường | | 4.5 | |
| `text.secondary` / `bg.surface` | Hint, chữ phụ | | 4.5 | |
| `text.inverse` / `brand.primary` | Nhãn nút chính | | 4.5 | |
| `text.inverse` / `status.danger` | Nhãn nút nguy hiểm | | 4.5 | |
| `brand.primary` / `bg.surface` | Liên kết | | 4.5 | |
| `status.danger` / `bg.surface` | Message lỗi | | 4.5 | |
| `border.strong` / `bg.surface` | Viền ô nhập (non-text) | | 3.0 | |
| Quy tắc | Giá trị | Nguồn |
|---|---|---|
| Hit target tối thiểu trên mobile | 44 × 44 px | WCAG 2.5.8 / `size.control.touch` |
| Focus luôn thấy được | ring 2px `focus.ring`, offset 2px | WCAG 2.4.7 |
| Không truyền nghĩa chỉ bằng màu | Badge luôn có nhãn chữ; lỗi luôn có icon + text | WCAG 1.4.1 |
| Mọi ô nhập có nhãn | `<label>` bao ngoài hoặc `aria-label` | WCAG 1.3.1 |
| Thứ tự focus | Theo `WF` §3.x.6 của từng US | |
## 7. Motion
| Việc | Thời lượng | Easing | Ghi chú |
|---|---|---|---|
| Hover nút / dòng | 120 ms | ease | |
| Toast vào/ra | 200 ms | ease-out | Thời gian hiển thị theo UICONV §5 |
| Modal mở | 160 ms | ease-out | Không dùng bounce |
| Skeleton shimmer | 1.2 s lặp | linear | Tắt khi `prefers-reduced-motion` |
## 8. Ngoại lệ đã duyệt
*`HIFI`/`FIGMA` lệch DS ⇒ phải có dòng ở đây. Không có dòng ⇒ lệch là lỗi.*
| # | Tài liệu | Token/component lệch | DS nói | Thực tế | Vì sao | Ai duyệt | Ngày |
|---|---|---|---|---|---|---|---|
## 9. Open Questions
| ID | Câu hỏi | Hỏi ai | Từ ngày | Chặn gì |
|---|---|---|---|---|
---
## Tự chấm
| # | Tiêu chí | ☐/✅ |
|---|---|---|
| 1 | `tokens.json` parse được; `tokens.css` sinh khớp (design-check T1 = ok) | |
| 2 | Mọi cặp tương phản ở §6 đạt ngưỡng (design-check T2 = ok) | |
| 3 | §3: mọi kiểu trình bày của UICONV §11 có lớp DS **và** có mặt trong `components.html` | |
| 4 | §4: mọi component có đủ default / hover / focus / disabled; component nhập liệu có Error | |
| 5 | `breakpoint.*` khớp UICONV §1; `size.content-max` khớp UICONV §1 | |
| 6 | Hai trạng thái rỗng trong `components.html` trông khác nhau | |
| 7 | §0 ghi rõ độ tin cậy; giá trị placeholder có `OQ` | |
| 8 | Có chữ ký Designer (hoặc PO ký thay + `DEC-nn` "không có Designer") | |