Skip to content

DOL Design System - Direction

activeUpdated

Scope: Triết lý, core pillars, anti-patterns cross-topic. Compact “why” layer. Technical topic files (same folder): typography.md, color.md, radius.md, spacing.md, shadow.md. Code reference: ../ui-style-guide/CORE.md (Tailwind classes, component recipes).

Guideline này định nghĩa cảm giác chung của mọi surface DOL (trừ KID - có guideline riêng). AI và designer được khuyến khích sáng tạo về layout, animation, visual treatment - miễn là kết quả giữ được bản sắc DOL và không phạm anti-patterns.

  • Professional nhưng ấm - không lạnh lẽo như enterprise dashboard, không rối như trang tin tức.
  • Rộng rãi, thoáng đãng - whitespace là feature, không phải lỗi.
  • Rõ ràng, dễ quét - hierarchy rõ bằng mắt, không cần đọc kỹ mới hiểu cấu trúc.
  • Tinh tế, không phô trương - chi tiết nhỏ tạo chất lượng (radius mềm, transition mượt, màu nhất quán).

Visual direction mặc định của DOL Design System:

  1. Semantic-first - ưu tiên token semantic trước; không set tay raw values nếu không có lý do rõ.
  2. Variable-first styling - variable là lớp mặc định; effect style dùng cho elevation/focus; paint style chỉ dùng khi là reusable decorative asset hoặc spec gọi đúng tên.
  3. Soft-large radius - controls và surfaces mặc định thiên về bo tròn mềm, không phải sharp-corner UI.
  4. Generous spacing - dùng khoảng trắng để tạo hierarchy rõ, nhóm element liên quan theo proximity trước khi thêm line/divider.

Áp dụng theo thứ tự này khi styling UI:

  1. Variable / semantic token = lớp mặc định cho text, fill, surface, border, radius, spacing, sizing.
  2. Effect style = chỉ dùng cho elevation, colored depth accent, focus ring.
  3. Paint style = chỉ dùng khi cần reusable decorative/media surface đã được canon đặt tên sẵn.

Quy tắc cứng:

  • Không dùng paint style để thay thế semantic text color, border color, background color cơ bản.
  • Không dùng effect style như cách bù cho spacing hoặc hierarchy yếu.
  • Nếu chưa có lý do rõ ràng, luôn quay về variable trước.

Technical detail: shadow.md §Variable-first rule + §Paint style usage.

Mỗi màu mang ý nghĩa cố định. DOL tuân thủ bảng Báo hiệu Hành Vi chung.

Canonical shade = -600 (NOT Tailwind’s default -500). Tất cả intent class dưới đây dùng shade 600 khi solid vivid.

IntentClass prefixCanonical valueVai trò
Brandbg-brand-*#D42525 (custom)Thương hiệu DOL, accent logo, CTA thương hiệu
Danger / Errorbg-red-*red-600Error, xóa, thao tác nguy hiểm
Successbg-green-*green-600Success, positive feedback, tick đúng
Warningbg-amber-*amber-600Warning nhẹ, near deadline, review
Infobg-blue-*blue-600Link, active state, progress, in-progress badge
Specialbg-purple-*purple-600Premium, feature đặc biệt, gamification
AIbg-sky-*sky-600AI features, smart actions, chatbot, magic/sparkles
Neutralbg-slate-*slate-* rangeText/border/surface. Không dùng gray-* / zinc-* / neutral-*. Không text-black.

Semantic aliases (preferred cho new code): bg-danger-*, bg-success-*, bg-warning-*, bg-info-*, bg-special-* - map xuống underlying Tailwind class.

Rules cứng:

  • Brand ≠ Danger. bg-red-* = danger/error only. bg-brand-* = custom class (NOT bg-red-*).
  • Canonical shade = -600 (NOT -500).
  • Text trên colored/inverse bg cần fixed white: dùng text-on-inverse-primary (--white-w100). text-white = --neutral-n00.
  • Không dùng bg-brand-* cho body text dài.
  • Tối đa 2 semantic accent colors đồng thời per view.

Áp dụng cho title, icon, tag/badge/card tint liên quan trực tiếp đến skill đó.

SkillColorRationale
ReadingEmerald/GreenTiếp thu, đọc hiểu
ListeningBlueLuồng âm thanh thông suốt
WritingAmber/YellowSáng tạo, tập trung viết
SpeakingRose (KHÔNG phải Brand Red)Tự tin, phát âm lớn
Full Test / Online TestPurpleĐa kỹ năng, đánh giá toàn diện
AI Features / Smart ActionsSky/CyanThông minh, gợi ý, magic

Technical detail: color.md §Semantic text colors + §Quick mapping by use case.

5. Critical accessibility - CVD (color blindness)

Section titled “5. Critical accessibility - CVD (color blindness)”

Khoảng 8% nam + 0.5% nữ có color vision deficiency.

Confusing pair: blue vs purple (info vs special). Normal ΔE = 21, deuteranopia ΔE = 2 → khoảng 5% users không phân biệt được.

Rule cứng khi blue + purple xuất hiện cùng:

  1. KHÔNG rely on color alone.
  2. Pair với icon hình dạng khác nhau + text label rõ ràng.
  3. Chart/data viz: dùng pattern + label, không chỉ màu.
  4. Nav/tab: thêm icon prefix bên cạnh label.

Nếu user phải distinguish 2 elements bằng visual only, không dùng blue + purple cùng nhau. Tách ra blue + green hoặc purple + amber.

Technical detail: color.md §CVD considerations (có code examples).

Clear voice, not loud voice - typography phục vụ việc đọc, không decorate cho UI.

  • 2 fonts only: Plus Jakarta Sans (heading/display) + Inter (body/label). Noto Serif dành riêng cho quote. Because DOL là education, text cần feel như textbook chất lượng - không phải marketing page đầy font-experiments.
  • Handwritten accent font exception (landing only): cho personal/emotional accent ngắn ≤8 từ, 1 lần/page max - Caveat / Pacifico / Dancing Script. KHÔNG cho body/heading/label. Recipe: ui-style-guide/landing.md §7.8.
  • Body baseline: 14px (--text-base). Không dùng <13px. Reading comfort > dense UI - DOL user đọc lâu, không scan nhanh.
  • Density taxonomy: fit / compact / standard / extended. standard = default cho đa số. Density là tool của context, không phải stylistic choice.
  • fit chỉ dùng cho text trang trí, 1 dòng duy nhất - không dùng cho content cần đọc. Dùng sai = text crop mid-word, user cảm giác app chưa tinh.

Technical detail: typography.md §Text scale + §Rule line-height theo độ dài nội dung.

Breathing room is content - whitespace không phải empty space, là nhịp thở để user tiêu hóa thông tin.

  • Generous spacing - khi phân vân giữa 2 gap values, chọn giá trị lớn hơn. Because DOL là learning context, user cần khoảng nghỉ mắt để xử lý - tight spacing đọc như productivity tool (wrong feel).
  • Hierarchy-first - tăng spacing giữa nhóm khác nhau trước khi thêm divider. Divider là last resort, spacing là first tool.
  • Atomic grouping: atom → molecule → organism → section, mỗi cấp có nhịp spacing riêng. User đọc UI như đọc văn bản có paragraph - cần cấp độ break.

Core laws:

  • Proximity - element cùng chức năng gần nhau hơn element khác nhóm.
  • Similarity - item cùng loại dùng cùng nhịp spacing/inset.

Technical detail: spacing.md §Spacing levels A-D + §Recommended defaults.

Pillowy confidence - controls cảm giác như pressed foam, không phải laser-cut acrylic.

  • Soft-large radius - user cảm thấy UI “mời chạm” thay vì “cấm kỵ”. Because DOL = education (trust + calm), sharp corners đọc như enterprise compliance dashboard - wrong feel cho learning context.
  • Radius scales with element height - bigger surface cần bigger curve để optical consistency (h48/r16, h64/r24). Không phải công thức để nhớ, là tỷ lệ để internalize.
  • Pill = purposeful commitment - chip/tag/capsule only. “Button muốn bo nhiều” là red flag - nếu nó muốn pill, có lẽ nó nên là chip.

Technical detail: radius.md §Control radius by element height + §Default control mapping.

Paper on desk, not neon on stage - shadow tạo depth tinh tế, không drama.

  • Neutral shadow = default elevation - shadow-neutral/to-bot/1..5 tùy mức nổi. Shadow như bóng nhẹ của trang giấy đặt trên mặt bàn - đủ để mắt nhận ra depth, không intrude vào reading flow.
  • Colored shadow (brand/info/success/etc.) chỉ dùng khi:
    • Cần accent có chủ đích theo brand/category
    • Surface mang tính campaign / special state / themed section
  • Không dùng colored shadow làm default elevation cho layout bình thường. Colored shadow là spotlight - dùng sai = sân khấu rực rỡ chứ không phải education UI.
  • Không thay focus ring bằng colored shadow level 3/4/5.
  • Tối đa 2 elevation levels đồng thời per view. Layer quá nhiều shadow = floating mess, user mất sense of depth order.

Technical detail: shadow.md §Default elevation + §Colored shadows.

🛑 Match-and-refuse (meta-rule for all §10 sub-tables): nếu code/design bạn sắp commit khớp một row trong bất kỳ sub-table nào dưới, STOP - rewrite approach, không chỉ swap value lẻ. DIRECTION §10 = philosophy + WHY; xem CORE.md §11 cho quick-ref Tailwind mapping.

<dol_anti_pattern scope=“direction-10-layout”>

ID❌ Không làmVì sao✅ Thay vào đó
01Content rộng hơn 1280px không có max-widthMắt user chạy quá xa giữa các từ; đọc thành marathon, không phải reading flowmax-w-[1120px] đến max-w-[1280px] + mx-auto
02Padding page <16px mobileKhông chỉ ugly - feels cheap app, user trust drops instant trên first impressionMin 16px mobile, 24-32px tablet, 32-60px desktop
03Section liền nhau không có khoảng cách rõUI như list không đoạn; user không biết chuyển context giữa blocks--section-gap-* (32-80px) hoặc divider nhẹ
04Grid quá đều, không focal pointEverything equal priority = nothing has priority; trang như Excel sheet vô hồnCho 1-2 element “to hơn” / “nổi hơn” dẫn mắt

</dol_anti_pattern>

<dol_anti_pattern scope=“direction-10-typography”>

ID❌ Không làmVì sao✅ Thay vào đó
01Hơn 3 cấp font-size trong 1 cardMỗi size = 1 hierarchy layer user phải parse; brain overload → skip cardTối đa 3 cấp: title → body → label
02Body text <13pxA11y fail + DOL có user lớn tuổi; readability > density cho learning contextBody tối thiểu 14px (--text-base)
03Heading + body cùng weightHierarchy invisible → user không biết đọc từ đâu; visual chaos = skipHeading nặng hơn body ít nhất 1 bậc
04Quá nhiều màu text trong 1 viewRainbow UI feels unprofessional; DOL là education, không phải children’s gameStick to semantic: emphasis / primary / secondary / placeholder

</dol_anti_pattern>

<dol_anti_pattern scope=“direction-10-color-brand”>

ID❌ Không làmVì sao✅ Thay vào đó
01bg-red-* cho brandBrand và danger trộn lẫn → user confuse CTA với cảnh báo; trust-crash instantBrand chỉ dùng custom class bg-brand-* (mapped #D42525). bg-red-* = danger only
02bg-brand-* cho error/dangerBrand feel biến thành “mọi thứ đang hỏng”; signal-noise invertedDanger = bg-red-* (canonical -600)
03Hơn 2 semantic accents đồng thờiEye không biết nhìn đâu trước; cognitive overload = UI thất bại1 brand + 1 status color per context
04bg-blue-* cho “mọi thứ nổi bật”Blue loãng ý nghĩa → mất signal active vs decoratedBlue = progress/info/active/link; nổi bật → bg-brand-*
05Shade -500 làm canonicalTW default là -500 nhưng DOL tune shade cho WCAG + aesthetic tại -600Luôn dùng -600 cho solid vivid intent
06text-white trên vivid bg (shade 500-600)Dark mode sẽ swap → text biến màu giữa theme; broken contrasttext-on-inverse-primary cố định trắng xuyên theme
07gray-* / zinc-* / neutral-*Neutral family split = inconsistent hover/border across componentsDùng slate-* duy nhất
08Background gradient rực rỡ toàn pageDOL = calm classroom, not casino landing - phá cảm giác space to thinkGradient nhẹ (slate-50 → white) hoặc chỉ hero/header, body giữ neutral
09Card trắng trên trắng không border/shadowBorder = edge definition; thiếu = card biến mất khi viewport thu nhỏBorder bắt buộc (border-slate-100 / border-slate-200); shadow bổ trợ

</dol_anti_pattern>

<dol_anti_pattern scope=“direction-10-spacing-depth”>

ID❌ Không làmVì sao✅ Thay vào đó
01Shadow quá đậm hoặc nhiều levels đồng thờiMỗi level = noise; UI feels như web 2010, mất modern feelTối đa 2 levels per view; ưu tiên neutral-1..3
02Padding nội bộ không đều 4 phíaFeels đối xứng sai → user perceive misalign dù không consciousBội số 4px; top/bottom ≥ left/right
03Element quá sát (<8px) khi không liên quanBrain nhóm chúng lại = hiểu sai structure; spacing là ngôn ngữ groupingGiữ 12-16px+ giữa nhóm không liên quan

</dol_anti_pattern>

<dol_anti_pattern scope=“direction-10-component-interaction”>

ID❌ Không làmVì sao✅ Thay vào đó
01Button không có hover/focusUser không biết clickable vs label; trust-gap “có chạm được không?”Min hover: brightness shift hoặc bg change
02Click target <32pxTouch miss rate tăng mobile, user rage-tap; app rating dropMin 36px height; 44px cho primary actions
03Transition đột ngột (instant)Layout change no motion = feels glitchy, context mất theo frame150-300ms ease-out cho UI transitions
04Loading state trắng trơnUser giả định app hỏng sau 2s blank; skeleton = reassuranceSkeleton / spinner / text “Đang tải…”

</dol_anti_pattern>

<dol_anti_pattern scope=“direction-10-responsive”>

ID❌ Không làmVì sao
01Text/layout y hệt desktop trên mobileChữ to quá, reading flow gãy; screen real-estate waste
02Ẩn nav trên mobile mà không có thay thếUser lạc giữa page, không back được; trap UX
03Horizontal scroll trên content chínhAnti-pattern từ 2015; user cảm giác app chưa modern/professional

</dol_anti_pattern>

These patterns reveal “AI made this” instantly. DOL canonical tokens correct nhưng vẫn produce slop nếu dính các pattern dưới. Match-and-refuse: nếu bạn sắp write một trong các PATTERN này, STOP và rewrite element với structure khác hoàn toàn (đừng chỉ swap value).

Naming convention: Universal patterns có ID slop-NN (canonical, defined here). Product-surface anti-patterns dùng namespace <product>-<topic>-NN (defined trong respective ui-style-guide/{landing,practice,data-entry}.md). AI agents có thể cite cả hai layers, e.g., “vi phạm slop-08 + practice-2.6-answer-cards row 1”.

Named pattern exceptions (đặc biệt cho slop-03 nested-cards): trước khi refuse nested composition, check ../pattern-registry.md - Constellation Block + future named patterns dùng nesting INTENTIONALLY với DIFFERENT treatment per tier (outer frame / middle bg / inner cells). slop-03 chỉ cấm CÙNG treatment chồng nhau, KHÔNG cấm intentional 3-tier composition.

<dol_anti_pattern scope=“direction-10-ai-slop-universal”>

IDPATTERNWHYREWRITE
slop-01 side-stripeborder-left hoặc border-right: ≥2px solid <color> trên card/list/alert#1 AI tell ở admin/dashboard/medical UIs; never looks intentionalFull border border border-slate-100 HOẶC background tint bg-blue-50 HOẶC leading icon/number. Không chỉ swap sang shadow inset.
slop-02 gradient-textbg-gradient-* + text-transparent + bg-clip-text trên heading/metricTop-3 AI tell; decorative without meaningSolid color (text-slate-900) + font weight/size cho emphasis
slop-03 nested-cardsCard (bg-white + border + shadow) chứa Card khác cùng treatmentVisual noise, excessive depth, flatten-failureFlatten: 1 outer card + inner content dùng spacing + typography hierarchy, KHÔNG nested containers
slop-04 monotonous-spacingCùng 1 gap/padding value (vd gap-4 everywhere) trong whole viewNo rhythm = layout monotone, feels templatedVary: atom=gap-2, molecule=gap-3, organism=gap-4, section=gap-8 (per §7)
slop-05 everything-centeredMultiple consecutive text-center trong siblings (section sau section)Every element centered = nothing stands out; lazy alignmentLeft-align body + asymmetric composition. Center reserved cho hero + CTA duy nhất.
slop-06 icon-tile-aboveBig icon box (rounded + tinted bg) trên mỗi heading trong feature listTemplated, makes site look AI-generated instantInline icon bên cạnh heading HOẶC no icon. Icon box reserved cho genuine feature card với purpose, không decoration.
slop-07 dark-glowshadow-[...rgba(brand-color)...] box-shadow với colored glow”Cool dark aesthetic” without design decisionsNeutral shadow (shadow-neutral/to-bot/N). Colored glow chỉ cho campaign/special state đã canon.
slop-08 bounce-easingcubic-bezier với negative values (overshoot) hoặc ease-bounce/elasticDated 2010s feel, real objects decelerate smoothlyease-out hoặc cubic-bezier(0.25, 1, 0.5, 1) (ease-out-quart)
slop-09 layout-animationCSS transition / transition-property of layout props (width/height/padding/margin) - NOT Tailwind transition-all when only transform/opacity/color/shadow actually changeLayout-prop transitions force repaint + reflow - performance tanks on slow devicesDon’t animate layout props. Use transition-property: transform, opacity, color, box-shadow (or Tailwind transition-all when CSS only changes these - shorthand is fine since nothing layout-ey animates). Height animation → grid-template-rows technique
slop-10 body-typography-loudBody text với uppercase + tracking-wider HOẶC text-justifyBody text treatment như label/hero = AI tell, hurts readabilityBody: normal case + normal tracking + text-left (not justified). Uppercase reserved cho label ≤3 words.

</dol_anti_pattern>

Automation: audit.sh catches slop-01, -02, -07, -08, -09, -10 at static scan. Slop-03, -04, -05, -06 need visual review (no reliable regex).

11. DOL English feature naming (domain-specific)

Section titled “11. DOL English feature naming (domain-specific)”

Tên chuẩn trên mọi surface:

FeatureTên chuẩn❌ Không dùng
PracticeKho bài tậpLuyện tập, Practice Hub
VocabularySổ từ vựngTừ vựng, Vocab
CoursesKhóa họcCourses
ProgressTiến độTheo dõi tiến độ

→ Xem thêm Playground: docs/DOL_ENGLISH_STYLE_GUIDE.md.

Smell tests trước khi coi UI hoàn thành - nếu một câu hỏi trả lời “không chắc” = chưa done.

  • Hierarchy rõ? - 2-second test: mắt user có biết đọc gì trước, gì sau, gì là optional?
  • Nhất quán? - Same element = same style everywhere? Nếu khác = user sẽ hỏi “cái này khác gì vậy?”
  • Token đúng vai trò? - Heading = emphasis, body = primary, phụ = secondary (không ngược)?
  • Breathing room? - Mắt có “chỗ nghỉ” giữa các nhóm, hay feel crammed/claustrophobic?
  • Interactive feedback? - Rê chuột qua clickable → có phản hồi, hay “dead silent”?
  • Mobile? - Thu viewport nhỏ → layout elegant adapt, hay gãy/overflow?
  • Edge states? - Empty / loading / error: user nhận message rõ ràng, hay màn hình trắng?
  • Semantic-first? - Không hardcode raw values (hex, px) khi đã có token tương ứng?
  • Blue + purple a11y? - Nếu CVD user dùng UI này, 2 element cùng màu có distinguishable?
  • AI slop test? - Nếu show UI này và nói “AI made this”, user có tin ngay không? Nếu có → review §10 AI Slop fingerprints để tìm pattern đang reveal AI-generated feel.
  • Topic files (same folder):
    • typography.md - font family, text scale, density taxonomy, text group matrix
    • color.md - semantic hierarchy, skill colors detail, shade scale math, CVD detail
    • radius.md - control / surface / overlay radius by height mapping
    • spacing.md - atomic levels A-D, wireframe defaults
    • shadow.md - shadow tier mapping, variable/effect/paint precedence, paint style inventory
  • Code reference: ../ui-style-guide/CORE.md (Tailwind classes, component recipes)
  • Deep reference:
    • ../../docs/tailwind-color-guideline.md (18-family mapping)
    • ../../docs/alpha-decomposition-spec.md (shade scale + alpha math)
    • ../../docs/color-system-rules.md (34 universal color rules)
  • See also: ../kid/Design System Guideline/KID_DS_Basic_Guideline.md (KID-specific)
  • Hub: README.md