Title / Description Hierarchy — Nghiên cứu từ các hệ thống lớn
Mục đích: Phân tích hệ thống typography hierarchy (Title + Description pairs) từ các design system hàng đầu, tập trung Google MD3 và shadcn/ui, rút ra nguyên tắc chung, và đề xuất áp dụng vào Prisma Design System.
1. Hai hệ thống trọng tâm
1.1. Material Design 3 (Google) — Hệ thống role-based
MD3 chia typography thành 5 role × 3 size = 15 tokens:
| Role | Large | Medium | Small | Mục đích |
|---|---|---|---|---|
| Display | 57px / 64 lh | 45px / 52 lh | 36px / 44 lh | Hero text, landing, branding |
| Headline | 32px / 40 lh | 28px / 36 lh | 24px / 32 lh | Page titles, content section headers |
| Title | 22px / 28 lh | 16px / 24 lh | 14px / 20 lh | Component headers, card titles |
| Body | 16px / 24 lh | 14px / 20 lh | 12px / 16 lh | Paragraph content, descriptions |
| Label | 14px / 20 lh | 12px / 16 lh | 11px / 16 lh | Buttons, tabs, tags, captions |
Nguyên tắc Title/Description trong MD3:
- Title và Body luôn đi theo cặp (pair): Title = tên gọi, Body = mô tả chi tiết
- Title dùng
Mediumweight (500), Body dùngRegularweight (400) → tạo contrast bằng weight, KHÔNG chỉ bằng size - Mỗi cặp Title/Body có 3 mức tương ứng: Large pair cho dialogs, Medium pair cho cards, Small pair cho list items
- Label là role riêng, KHÔNG trộn với Title — Label cho UI control, Title cho content heading
MD3 cặp Title/Description canonical:
| Ngữ cảnh | Title token | Description token | Weight gap | Size gap |
|---|---|---|---|---|
| Dialog | Title Large (22px/500) | Body Medium (14px/400) | 100 | 8px (3 step) |
| Card | Title Medium (16px/500) | Body Medium (14px/400) | 100 | 2px (1 step) + weight |
| List item | Title Small (14px/500) | Body Small (12px/400) | 100 | 2px (1 step) + weight |
| App bar | Title Large (22px/400) | — | — | — |
| Navigation | Label Large (14px/500) | — | — | — |
Insight: MD3 dùng weight làm axis chính để phân biệt Title vs Description, chỉ cần ít nhất 1 step size gap. Đây là khác biệt lớn so với các DS khác.
1.2. shadcn/ui — Hệ thống utility-first
shadcn KHÔNG ship typography tokens/components mặc định — thay vào đó cung cấp utility class recipes dựa trên Tailwind CSS:
| Role | Tailwind Classes | Effective Size | Weight | Mục đích |
|---|---|---|---|---|
| h1 | text-4xl font-extrabold tracking-tight |
36px (2.25rem) | 800 | Page title, hero |
| h2 | text-3xl font-semibold tracking-tight |
30px (1.875rem) | 600 | Section heading |
| h3 | text-2xl font-semibold tracking-tight |
24px (1.5rem) | 600 | Subsection heading |
| h4 | text-xl font-semibold tracking-tight |
20px (1.25rem) | 600 | Component heading |
| p | leading-7 |
16px (1rem) | 400 | Body paragraph |
| Lead | text-xl text-muted-foreground |
20px | 400 | Subtitle / description dưới heading |
| Large | text-lg font-semibold |
18px (1.125rem) | 600 | Inline emphasis, dialog title |
| Small | text-sm font-medium leading-none |
14px (0.875rem) | 500 | Label, form label |
| Muted | text-sm text-muted-foreground |
14px | 400 | Helper text, description, caption |
shadcn Color Token Convention (bg/fg pairs):
--background / --foreground ← Page level (Ground)
--card / --card-foreground ← Card level
--popover / --popover-foreground ← Surface/overlay level
--muted / --muted-foreground ← Description, secondary text
--primary / --primary-foreground ← Action elements
--secondary / --secondary-foreground ← Secondary actions
--destructive / --destructive-foreground
Nguyên tắc Title/Description trong shadcn:
- Heading + Lead = cặp chính thức →
h1+Lead(text-xl text-muted-foreground) là pattern phổ biến nhất - Weight gradient rõ ràng: h1=extrabold(800) → h2-h4=semibold(600) → Large=semibold(600) → Small=medium(500) → p/Muted=regular(400)
- Color làm axis chính cho description:
text-muted-foreground= signal rõ ràng "đây là description" - Không có Label riêng: shadcn dùng
Small(text-sm font-medium) cho cả label và compact title - Card pattern:
CardTitledùngtext-2xl font-semibold+CardDescriptiondùngtext-sm text-muted-foreground
shadcn cặp Title/Description canonical:
| Component | Title class | Description class | Cách tạo contrast |
|---|---|---|---|
| Card | text-2xl font-semibold (24px/600) |
text-sm text-muted-foreground (14px/400) |
Size + Weight + Color |
| Dialog | text-lg font-semibold (18px/600) |
text-sm text-muted-foreground (14px/400) |
Size + Weight + Color |
| Alert | text-sm font-medium (14px/500) |
text-sm [&_p]:leading-relaxed (14px/400) |
Weight only |
| Page | text-4xl font-extrabold (36px/800) |
text-xl text-muted-foreground (20px/400) |
Size + Weight + Color |
| Toast | text-sm font-semibold (14px/600) |
text-sm opacity-90 (14px) |
Weight + Opacity |
Insight: shadcn luôn dùng 3 trục (Size + Weight + Color) cho các cặp lớn (Card, Page), nhưng cho phép chỉ 1 trục (Weight) cho compact pairs (Alert, Toast).
2. Hệ thống bổ trợ
2.1. IBM Carbon Design System
Carbon chia thành 2 type sets — Productive (fixed) và Expressive (responsive):
| Category | Productive (fixed) | Expressive (responsive) |
|---|---|---|
| Heading 01 | 14px / 18 lh | 14px → 16px |
| Heading 02 | 16px / 22 lh | 16px → 20px |
| Heading 03 | 20px / 26 lh | 20px → 28px |
| Heading 04 | 28px / 36 lh | 28px → 36px |
| Heading 05 | 32px / 40 lh | 32px → 60px |
| Body 01 | 14px / 20 lh | 14px / 20 lh |
| Body 02 | 16px / 24 lh | 16px / 24 lh |
| Helper text | 12px / 16 lh | 12px / 16 lh |
| Label 01 | 12px / 16 lh | 12px / 16 lh |
Key takeaway: Productive = app/dashboard UI (fixed sizes), Expressive = marketing (responsive). Carbon tách utility styles (Label, Helper) ra khỏi content hierarchy.
2.2. Atlassian Design System
Atlassian dùng T-shirt sizing (XXL→XXS):
| Token | Size | Weight | Mục đích |
|---|---|---|---|
font.heading.xxlarge |
29px | 700 | Brand, marketing |
font.heading.large |
22px | 700 | Page titles |
font.heading.medium |
17px | 700 | Section headers, modal titles |
font.heading.small |
14px | 600 | Card titles |
font.heading.xsmall |
12px | 600 | Compact titles (flags) |
font.body.large |
17px | 400 | Long-form reading |
font.body (default) |
14px | 400 | Component descriptions |
font.body.small |
12px | 400 | Fine print |
Key takeaway: Heading + Body cùng tier = cặp, e.g. heading.small (14px/600) + font.body.small (12px/400).
2.3. Ant Design
Ant Design dùng pentatonic scale (10 bậc, 12→56px, base=14px):
- Font weight: Regular(400) + Medium(500) đủ; Semibold(600) cho bold English
- Khuyến nghị: 3–5 font sizes per page
- Title/Description pair: cách nhau ≥ 2 bậc trong scale
3. So sánh MD3 vs shadcn — hai triết lý
| Tiêu chí | MD3 | shadcn |
|---|---|---|
| Mô hình | Role-based tokens (semantic) | Utility-class recipes (flexible) |
| Số lượng roles | 5 roles × 3 sizes = 15 | 9 recipes (h1-h4, p, Lead, Large, Small, Muted) |
| Weight range | 400–500 (chỉ regular/medium) | 400–800 (regular→extrabold) |
| Color as hierarchy axis | Không định nghĩa (để cho theme) | Có sẵn: foreground vs muted-foreground |
| Label | Role riêng biệt | Gộp chung với "Small" |
| Min font size | 11px (Label Small) | 14px (text-sm) |
| Title/Desc gap strategy | Weight-first (100 gap) + size | Size-first + Weight + Color (3 axes) |
| Token architecture | Semantic tokens → CSS | CSS variables (bg/fg pairs) → Tailwind |
Bảng mapping chéo:
| Vai trò | MD3 token | shadcn recipe | Prisma role |
|---|---|---|---|
| Page hero | Display Large | text-4xl font-extrabold |
display-lg |
| Page title | Headline Large | text-3xl font-semibold |
headline-md |
| Section title | Headline Small | text-2xl font-semibold (h3) |
headline-sm |
| Component title | Title Medium | text-lg font-semibold (Large) |
title-md |
| Card title | Title Medium | text-2xl font-semibold (CardTitle) |
title-md |
| Body text | Body Medium | leading-7 (p) |
body-md |
| Description | Body Medium | text-sm text-muted-foreground (Muted) |
body-sm muted |
| Subtitle | Body Large | text-xl text-muted-foreground (Lead) |
body-lg muted |
| Form label | Label Medium | text-sm font-medium (Small) |
label-md |
| Caption | Label Small | text-sm text-muted-foreground |
caption |
4. Quy luật chung rút ra (Cross-System Patterns)
4.1. Title / Description luôn đi theo CẶP
| Pattern | Title Role | Description Role | Gap |
|---|---|---|---|
| Hero pair | Display / Headline LG | Body LG / Lead | ≥ 3 bậc |
| Section pair | Headline / h2-h3 | Body MD / Muted | 2 bậc |
| Component pair | Title MD / Large | Body SM / Muted | 1–2 bậc |
| Compact pair | Title SM / Small | Caption / Muted | 1 bậc |
4.2. Contrast Strategy — 3 trục
┌─────────────────────────────────────────────────────┐
│ CONTRAST AXES │
│ │
│ 1. SIZE ──────── Title lớn hơn Description ≥ 2 step │
│ 2. WEIGHT ────── Title: semibold/bold (500-700) │
│ Description: regular (400) │
│ 3. COLOR ─────── Title: foreground (high contrast) │
│ Description: muted-foreground │
│ │
│ → MD3: weight-first (min 1 step size + weight gap) │
│ → shadcn: 3-axis cho large, weight-only cho compact │
│ → Prisma: dùng TỐI THIỂU 2/3 trục tại mọi pair │
└─────────────────────────────────────────────────────┘
4.3. Depth-Based Title Levels
Page Level
┌─────────────────────────────────────────────┐
│ Display / Headline LG ← Page Title │
│ Body LG / Lead ← Page Description │
│ │
│ Section Level │
│ ┌─────────────────────────────────────────┐ │
│ │ Headline MD / SM ← Section Title │ │
│ │ Body MD / Muted ← Section Desc │ │
│ │ │ │
│ │ Component Level │ │
│ │ ┌─────────────────────────────────────┐ │ │
│ │ │ Title MD / SM ← Component Title │ │ │
│ │ │ Body SM / Muted ← Component Desc │ │ │
│ │ │ │ │ │
│ │ │ Item Level │ │ │
│ │ │ ┌──────────────────────────────┐ │ │ │
│ │ │ │ Label / Small ← Item Title │ │ │ │
│ │ │ │ Caption / Muted ← Item Desc │ │ │ │
│ │ │ └──────────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
4.4. Quy tắc vàng (Golden Rules)
- Rule of 2: Title và Description ít nhất cách nhau 2 font-size step (trừ compact pair)
- Weight Separation: Title LUÔN nặng hơn Description (≥ 100 gap)
- Color Hierarchy: Title =
foreground, Description =muted-foreground(giảm 40-50% contrast) - One Display per Page: Chỉ 1 Display style trên toàn trang
- 3-5 Scale Rule: MD3 + Ant Design đều khuyến nghị ≤ 5 typography styles trên 1 trang
- Productive vs Expressive: App UI → fixed sizes, Landing/Marketing → responsive sizes
5. Áp dụng vào Prisma Design System
5.1. Prisma hiện tại đã có gì?
Prisma đã có hệ thống 6 roles × 3 sizes = 16 variants (hybrid MD3 + shadcn):
Display (XL, LG, MD) → 128px, 72px, 48px
Headline (LG, MD, SM) → 36px, 30px, 24px
Title (LG, MD, SM) → 20px, 18px, 16px
Body (LG, MD, SM) → 18px, 16px, 14px
Label (LG, MD, SM) → 16px, 14px, 12px
Caption → 12px
Color tokens (shadcn convention):
--foreground / --muted-foreground ← Ground layer text
--card-foreground ← Card layer text
--surface-foreground ← Surface layer text (popover equiv)
5.2. Mapping vào 3 Elevation Layers
┌──────────────────────────────────────────────────────────────┐
│ GROUND LAYER (page-level content) │
│ Background: --background / --canvas │
│ │
│ ┌── Page Title ───────────────────────────────────────────┐ │
│ │ Role: headline-lg / headline-md │ │
│ │ Weight: semibold (600) │ │
│ │ Color: var(--foreground) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ┌── Page Description ─────────────────────────────────────┐ │
│ │ Role: body-lg / body-md │ │
│ │ Weight: regular (400) │ │
│ │ Color: var(--muted-foreground) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ CARD LAYER (component-level) │ │
│ │ Background: --card │ │
│ │ │ │
│ │ ┌── Card Title ───────────────────────────────────┐ │ │
│ │ │ Role: title-lg / title-md │ │ │
│ │ │ Weight: semibold (600) │ │ │
│ │ │ Color: var(--card-foreground) │ │ │
│ │ └─────────────────────────────────────────────────┘ │ │
│ │ ┌── Card Description ─────────────────────────────┐ │ │
│ │ │ Role: body-sm / body-md │ │ │
│ │ │ Weight: regular (400) │ │ │
│ │ │ Color: var(--muted-foreground) │ │ │
│ │ └─────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────────┐ │ │
│ │ │ SURFACE LAYER (overlay / elevated) │ │ │
│ │ │ Background: --surface │ │ │
│ │ │ │ │ │
│ │ │ ┌── Surface Title ────────────────────────┐ │ │ │
│ │ │ │ Role: title-md / title-sm │ │ │ │
│ │ │ │ Weight: semibold (600) │ │ │ │
│ │ │ │ Color: var(--surface-foreground) │ │ │ │
│ │ │ └─────────────────────────────────────────┘ │ │ │
│ │ │ ┌── Surface Description ──────────────────┐ │ │ │
│ │ │ │ Role: body-sm / label-md │ │ │ │
│ │ │ │ Weight: regular (400) │ │ │ │
│ │ │ │ Color: var(--muted-foreground) │ │ │ │
│ │ │ └─────────────────────────────────────────┘ │ │ │
│ │ └──────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
5.3. Elevation × Typography Matrix
| Elevation | Title Role | Description Role | Label Role | Size Gap | Ví dụ |
|---|---|---|---|---|---|
| Ground | headline-lg→headline-sm |
body-lg→body-md |
label-md |
≥ 2 bậc | Page header, section |
| Card | title-lg→title-md |
body-md→body-sm |
label-sm |
≥ 2 bậc | Card, stat widget |
| Surface | title-md→title-sm |
body-sm→caption |
label-sm |
1–2 bậc | Dialog, tooltip, toast |
5.4. Component Typography Spec
| Component | Layer | Title | Description | Label | Caption |
|---|---|---|---|---|---|
| Page Header | Ground | headline-md |
body-md muted |
– | – |
| Section Header | Ground | headline-sm |
body-sm muted |
– | – |
| Card | Card | title-md |
body-sm muted |
label-sm |
caption |
| Stat Widget | Card | label-md (name) |
– | headline-sm (value) |
caption (trend) |
| List Item | Card | title-sm / body-md bold |
body-sm muted |
label-sm |
caption |
| Dialog | Surface | title-lg |
body-md muted |
label-md |
– |
| Dropdown Item | Surface | body-sm |
– | – | caption |
| Toast | Surface | title-sm |
body-sm muted |
– | caption |
| Tooltip | Surface | – | body-sm |
– | – |
| App Bar | Ground/Card | title-md (page) |
– | label-sm (actions) |
– |
| Sidebar | Ground | title-sm (section) |
– | label-md (nav) |
caption (badge) |
| Table | Card | title-sm (header) |
body-sm (cell) |
label-sm (status) |
caption (meta) |
| Form Field | Card | – | body-sm (helper) |
label-md (label) |
caption (error) |
5.5. Anti-patterns
| ❌ Sai | ✅ Đúng | Lý do |
|---|---|---|
headline-lg cho Card title |
title-md cho Card title |
Card ở Card layer, headline cho Ground |
| Title và Desc cùng size, chỉ khác weight | Title ≥ 2 step lớn hơn (trừ compact) | Weight alone không đủ trên mobile |
| 6+ font sizes trên 1 page | Max 4–5 sizes + variation qua weight/color | Quá nhiều gây rối visual |
Desc cùng foreground với Title |
Desc phải dùng muted-foreground |
Color axis tạo hierarchy |
Dialog title dùng headline-md |
Dialog title dùng title-lg |
Dialog = Surface layer |