Skip to content

Audit Design System 04.10.2026 (SRC-1227) ​

Chủ dự án 04.10.2026: "Rà soát toàn bộ các design system, xem ổn không, và ổn hay không ổn thì được đánh giá theo tiêu chuẩn nào? Audit, có report. Rồi fix và nâng cấp design system."

Phạm vi: packages/design-system/ (token, CSS, art/, ui/), lớp shadcn của 11 app React, bốn site VitePress, và DS-001 (index.md).

1. Kết luận một dòng ​

Nền móng ổn, đường phân phối hỏng. Token, contrast, bộ ba Motion + shadcn + Tailwind đều đạt và có cổng máy canh. Nhưng thứ DS-001 hứa từ đầu, "app giữ bản sao Y HỆT của component canonical", không có máy nào kiểm, và đo ra thì 46 bản sao đã lệch. Lệch theo hướng tệ nhất: một bản sửa đi vào bản sao của MỘT app rồi dừng ở đó, nên ba lỗi đã sửa xong ở chỗ này vẫn sống ở chỗ khác.

2. Tiêu chuẩn đánh giá ​

"Ổn" không đo bằng cảm giác. Tám tiêu chí dưới đây, mỗi tiêu chí có một câu hỏi trả lời được bằng máy và một nguồn nói vì sao nó quan trọng. Năm tiêu chí đầu là luật riêng của Nemo12 (đã có trong DS-001); ba tiêu chí sau lấy từ chuẩn ngoài.

#Tiêu chíCâu hỏi đoNguồnNgưỡng đạt
T1Một nguồn tokenCó app nào khai lại bảng màu không?DS-001 §5d, RISK-0120 app
T2Bộ ba bắt buộc có mặtApp React nào thiếu Motion / shadcn / Tailwind, hay có thư viện UI thứ hai?DS-001 §0, SRC-6500 app
T3Bộ ba đủ mớiDải phiên bản có tụt major/minor so với registry?SRC-6530 gói
T4Một nguồn componentBản sao trong app có trùng canonical không? Primitive shadcn có bị fork?DS-001 §1, §2c, §5c0 lệch không khai
T5Màu đi qua tokenBao nhiêu chỗ viết cứng hex trong class/style của TSX?DS-001 §1≤ 10 chỗ, có lý do
T6Tương phảnCặp chữ/nền nào dưới ngưỡng?WCAG 2.2 AA §1.4.3 (4,5:1 chữ thường, 3:1 chữ lớn)0 cặp mới
T7Hành vi truy cậpHộp nổi có focus trap + Escape + trả focus? Vùng chạm ≥ 40px?WAI-ARIA APG (Dialog), WCAG 2.2 §2.5.8mọi hộp nổi dùng chung
T8Tài liệu đọc đượcSố mục trong DS-001 có trùng? Mỗi luật có lý do và cổng?Luật docs một nguồn của repo0 số mục trùng

T4 là tiêu chí chưa từng có cổng trước đợt này, và là chỗ hỏng.

3. Kết quả đo (trước khi sửa) ​

#Kết quảĐạt?Cổng
T10 app khai lại bảng màu✅check-shadcn-tokens
T211/11 app React đủ bộ ba✅check-design-stack
T3motion 14.0.0 · tailwindcss 4.3.3 · radix-ui 1.6.7 · cva 0.7.1, 16 app ghim cùng số✅check:ui-latest
T446 bản sao lệch (21 component Nemo12 + 25 primitive shadcn), 3 bản sao không ai import, 9/23 primitive có ≥ 2 biến thể❌không có
T56 chỗ hex trong class (5 marlins, 1 learn) + 2 trong style✅không có
T6257/257 cặp đạt✅contrast-check
T7Popover marlins thiếu nền đặc + portal về gốc theme; MasteryMap chỉ có focus trap ở marlins❌không có
T8DS-001 dài 1.539 dòng, hai mục cùng số 2·1·17, mục 4b…4j nằm dưới §5⚠️check:docs không bắt

4. Ba lỗi thật mà T4 che đi ​

Đây là lý do T4 là tiêu chí quan trọng nhất của đợt này: không phải vì "file khác nhau thì xấu", mà vì mỗi chỗ lệch là một bản sửa đã làm xong mà người dùng của app khác không bao giờ nhận được.

  1. Hình vẽ biến mất ở b21, coral, web. SRC-182 kéo 19 màu tô xuống dưới ngưỡng sáng 0,86 vì ~#F2F2F2 trên thẻ trắng làm hình vẽ biến mất. Bản sửa nằm ở learn, marlins, tutors. Canonical và ba app còn lại vẫn giữ bảng cũ.
  2. Popover trong suốt ở marlins. Nemo12 chưa từng khai --popover; lớp shadcn mặc định bg-popover cho nền trong suốt, và portal ra <body> rơi khỏi scope token của .n12-deep. Learn gặp đúng lỗi này trên production (SRC-878) và đã sửa; marlins, chạy toàn bộ trên nền biển sâu, vẫn dùng bản gốc shadcn.
  3. Tour lệch ba chiều. Canonical có bản sửa StrictMode (tour có thể không bao giờ tự mở nếu effect bị dọn trước khi timer chạy) nhưng không app nào chép về. Learn có nhãn tiếng Anh cho sân luyện, nút shadcn và vùng chạm 40px; marlins có cả hai thiếu sót.

Thêm hai dấu hiệu cùng gốc:

  • Cùng một preset bị phát minh hai lần. gull (Reveal, SRC-836) và web (Appear, SRC-746) cùng gặp lỗi whileInView để khối đứng ở opacity: 0, và mỗi bên tự viết preset riêng. Learn còn giữ một bản Motion thứ hai trong ielts/Motion.tsx. Tám app còn lại không có preset nào.
  • Canonical thành bản CŨ NHẤT. 8/17 component Nemo12 có bản sao mới hơn canonical. Người sửa sửa chỗ họ đang đứng, không có gì nhắc họ đưa về nguồn.

5. Đã sửa trong đợt này ​

ViệcChi tiết
Cổng T4 mớiscripts/check-ds-copies.mjs trong npm run check:code: 143 bản sao phải trùng canonical, primitive shadcn mới phải vào canonical trước, mọi fork phải khai lý do
Lệnh đồng bộnpm run ds:sync: sửa ở canonical rồi chép ra mọi bản sao
Manifestpackages/design-system/copies.json: ai là bản sao của ai, và 5 fork có lý do
Canonical shadcnpackages/design-system/shadcn/: 23 primitive, lấy bản của learn (bản cụm /style trưng bày, SRC-942); card lấy bản mentors vì có thêm cardClass (SRC-584) mà render giống hệt
Hợp nhất canonicalpalette (SRC-182) · CoursesPanel · SiteFooter (prop brand) · MasteryMap (focus trap) · ReferralPanel (tầng hai SRC-1026) · FindingNemo + AboutMarlins (contrast SRC-831) · Tour (nhãn EN + Button + 40px + bản sửa StrictMode)
Preset AppearVào Motion.tsx canonical; Reveal của gull và learn đổi sang Appear. Có mặt ở cả 11 app
Đồng bộ ra app45 bản sao được chép lại từ canonical; ba lỗi ở §4 đóng lại ở mọi app
Xoá bản sao chếtweb/AboutMarlins.tsx, web/SwimmingLoader.tsx, admin/SwimmingLoader.tsx: không ai import
DS-001Thêm §1·1 (luật bản sao + cổng), sửa số mục 2·1·17 trùng

6. Kết quả đo (sau khi sửa) ​

#TrướcSau
T446 lệch, không cổng0 lệch, 143 bản sao trùng canonical, 5 fork có lý do, cổng chặn CI
T7Popover + MasteryMap chỉ đúng ở một appĐúng ở mọi app có chúng
T8Hai mục cùng sốSố mục duy nhất

T1, T2, T3, T5, T6 giữ nguyên trạng thái đạt.

7. Nợ còn lại, xếp theo giá trị ​

  1. mm dựng tay button/input/textarea, không có radix-ui. Khai fork có chữ NỢ trong copies.json. Trả: cài canonical, chuyển chỗ gọi sang variant="ghost" size="icon".
  2. Bản sao là cách phân phối, không phải đích đến. Đích đến là app import thẳng từ @nemo12/design-system/ui/* như đã làm với CSS. Cản trở: các component dùng @/components/ui/* và ./Motion theo đường dẫn tương đối của app. Cổng T4 giữ cho bản sao không lệch trong lúc chưa đi được bước đó.
  3. DS-001 cần một bản tóm tắt đọc trong năm phút. Bốn lớp visual direction (v0.3 → v0.4 → v1.0 → các mục 2·1·x) chồng nhau, mỗi lớp ghi "ĐÈ LÊN" lớp trước. Người mới phải đọc cả 1.500 dòng mới biết luật nào còn hiệu lực.
  4. T5 không có cổng. 8 chỗ hex hiện nay đều có lý do, nhưng không gì ngăn chỗ thứ chín.

8. Cách chạy lại audit này ​

bash
npm run check:code                      # T1, T2, T4, T6 (chặn CI)
npm run check:ui-latest                 # T3 (cần mạng, không chặn CI)
npm run ds:sync                         # sau khi sửa một canonical