Sizes (Contained, Circle)
In-Context Usage (iOS Settings Style)
Lead Icon Component Generation Skill
📦 Atomic Mapping: See ATOMIC-MAPPING.md for complete token spec.
Skill này hướng dẫn bạn (AI Agent) tạo component Lead Icon — icon đứng trước nội dung (leading position) trong list, card, navigation, với optional container (circle/square).
1. Mục tiêu (Objective)
Tạo leading icon component hỗ trợ naked (bare icon) và contained (icon trong circle/square bg), 5 sizes, 7 semantic colors, density-aware radius. Tích hợp 100% Design Tokens.
2. AI Context & Intent
Khi nào dùng Lead Icon?
- List items: Settings, navigation, action lists — icon trước title
- Card headers: Metric cards, feature cards — icon trước heading
- Navigation: Sidebar, bottom nav — icon trước label
- Status indicators: Colored circle icon for states
Phân biệt với component khác
| Tình huống |
Component đúng |
Lý do |
| Icon trước text trong list/card |
Lead Icon |
Container + sizing + semantic color |
| Icon đơn lẻ inline |
ds-icon |
No container, just SVG sizing |
| Ảnh đại diện user |
Avatar |
Image + initials fallback + status |
| Logo / brand mark |
Image |
Different aspect ratios |
Quan hệ với ds-icon
ds-icon → Raw SVG wrapper (size + color only, NO container)
ds-leadicon → Icon + optional bg container (size + color + bg + shape)
↳ Inner SVG inherits ds-icon stroke behavior
3. Ngữ nghĩa & Phân loại
3.1. Modes
| Mode |
Mô tả |
Use case |
| contained (default) |
Icon trong circle/square có background |
iOS Settings, grouped lists, emphasis |
| naked |
Icon trơn, không container bg |
Flat lists, Android style, minimal |
3.2. Shapes (Contained only)
| Shape |
Token |
Density behavior |
| circle (default) |
var(--radius-full) = 9999px |
Density-invariant — luôn tròn |
| square |
var(--comp-radius) |
Density-aware — 4px→8px→16px |
3.3. Sizes
| Size |
Container |
Icon inner |
Token pair |
xs |
24px |
16px |
spacing-6 / icon-sm |
sm |
28px |
16px |
spacing-7 / icon-sm |
md (default) |
32px |
20px |
spacing-8 / icon-md |
lg |
40px |
24px |
spacing-10 / icon-lg |
xl |
48px |
24px |
spacing-12 / icon-lg |
3.4. Semantic Colors
| Variant |
Contained BG |
Contained FG |
primary-muted (default) |
--primary-muted |
--accent-foreground |
primary |
--primary |
--primary-foreground |
destructive |
--destructive |
--destructive-foreground |
destructive-muted |
--destructive-muted |
--destructive-muted-foreground |
success |
--success |
--success-foreground |
success-muted |
--success-muted |
--success-muted-foreground |
warning |
--warning |
--warning-foreground |
warning-muted |
--warning-muted |
--warning-muted-foreground |
info |
--info |
--info-foreground |
info-muted |
--info-muted |
--info-muted-foreground |
muted |
--muted |
--muted-foreground |
4. CSS Classes
| Class |
Mô tả |
.ds-leadicon |
Base — md, circle, primary-muted |
.ds-leadicon--xs/sm/lg/xl |
Size modifiers |
.ds-leadicon--circle |
Circle shape (default) |
.ds-leadicon--square |
Square shape — density-aware radius |
.ds-leadicon--naked |
No background container |
.ds-leadicon--primary |
Solid blue bg + white fg |
.ds-leadicon--primary-muted |
Soft blue bg + accent fg |
.ds-leadicon--destructive |
Solid red bg + white fg |
.ds-leadicon--destructive-muted |
Soft red bg + red fg |
.ds-leadicon--success |
Solid green bg + white fg |
.ds-leadicon--success-muted |
Soft green bg + green fg |
.ds-leadicon--warning |
Solid orange bg + white fg |
.ds-leadicon--warning-muted |
Soft amber bg + amber fg |
.ds-leadicon--info |
Solid cyan bg + white fg |
.ds-leadicon--info-muted |
Soft sky bg + sky fg |
.ds-leadicon--muted |
Gray bg + muted fg |
5. Props & API
interface LeadIconProps {
/** Lucide icon element */
icon: ReactNode;
/** Size preset */
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
/** Shape */
shape?: 'circle' | 'square';
/** Mode */
mode?: 'contained' | 'naked';
/** Semantic color */
color?: 'primary' | 'primary-muted' | 'destructive' | 'destructive-muted' | 'success' | 'success-muted' | 'warning' | 'warning-muted' | 'info' | 'info-muted' | 'muted';
}
6. Accessibility
aria-hidden="true" on icon if decorative (label text adjacent)
role="img" + aria-label if icon IS the label
- SVG uses
stroke: currentColor for auto color inheritance
7. Best Practices
- Strictly Lucide Icons — NO emoji, NO external icons
- No hardcode — ALL sizes/colors from tokens
- Square radius = density — uses
var(--comp-radius), NOT var(--radius-md)
- Layer-neutral —
ds- prefix, works at any elevation
- Consistent sizing — same size across all items in a list group
8. Example Usage
<!-- iOS Settings: square, sm, colored bg -->
<span class="ds-leadicon ds-leadicon--sm ds-leadicon--square ds-leadicon--primary">
<svg><!-- lucide wifi --></svg>
</span>
<!-- Card header: circle, lg -->
<span class="ds-leadicon ds-leadicon--lg ds-leadicon--success">
<svg><!-- lucide trending-up --></svg>
</span>
<!-- Action list: naked, md -->
<span class="ds-leadicon ds-leadicon--naked ds-leadicon--destructive">
<svg><!-- lucide trash --></svg>
</span>
9. Anatomy
┌─────────────────────────┐
│ Container (Circle/Sq) │ ← width/height: --spacing-{size}
│ ┌─────────────────┐ │ ← border-radius: --radius-full (circle)
│ │ │ │ or --comp-radius (square, density-aware)
│ │ SVG Icon │ │ ← width/height: --icon-{sm|md|lg}
│ │ (Lucide) │ │ ← stroke: currentColor (inherits fg)
│ │ │ │
│ └─────────────────┘ │
│ │ ← background: semantic color token
│ │ ← color (fg): paired semantic foreground
└─────────────────────────┘
Naked mode: Container bg = transparent, fg = semantic color directly
2 layers: Container (sizing + bg + radius) → SVG Icon (inner sizing + fg inheritance).
No internal padding token — icon centering via align-items: center + justify-content: center.
10. Style Decision Matrix — Khi nào dùng style nào
Rule: Chọn sai style = hỏng visual hierarchy. Bảng dưới đây là MANDATORY cho Agent.
10.1. Mode: contained vs naked
| Context |
Mode |
Rationale |
Ref |
| iOS Settings list |
contained |
HIG: colored icon container phân biệt categories |
Apple HIG |
| Card header — KPI / metric / feature |
contained |
Icon = visual anchor cho card, cần emphasis |
MD3 Card anatomy |
| Status indicator — chip-like |
contained |
Color BG reinforces semantic meaning |
C4 |
| Action list — Share, Copy, Delete |
naked |
Icon supplementary, text là primary label |
MD3 List |
| Flat nav — sidebar, bottom nav |
naked |
Android/Material: icon + label, no extra chrome |
MD3 Nav |
| Minimal / clean design |
naked |
Less noise, deference to content |
HIG Deference |
| Dashboard grid — high density |
naked |
contained icons ở xs/sm tạo visual clutter |
NNG H8 |
10.2. Shape: circle vs square
| Context |
Shape |
Rationale |
Ref |
| iOS-style settings rows |
square |
Apple HIG Settings luôn dùng rounded-square container |
Apple HIG |
| Profile / person-related |
circle |
Convention: avatar/user = circle |
MD3 + HIG |
| Generic list items |
circle |
Default — softer, approachable |
HIG Clarity |
| Grid / matrix layout (tiles) |
square |
Tiles align tốt hơn in grid, no wasted corners |
A1 Grid align |
| Card header icon |
circle |
Default — adds visual softness |
MD3 Card |
| Status with category label |
square |
Square = "category", circle = "entity" |
Convention |
10.3. Color: solid vs muted
| Scenario |
Variant |
Why |
❌ Anti-pattern |
| Primary CTA context — icon next to main action |
primary (solid) |
High contrast = emphasis, CTA visual anchor |
❌ primary-muted — quá nhẹ |
| Informational list — settings / navigation |
primary-muted |
Soft bg, focus vào text label |
❌ primary solid — quá nặng cho mỗi row |
| Destructive action — Delete row |
destructive (naked) |
Clear danger signal khi paired với red text |
❌ destructive-muted — weakens warning |
| Error state heading |
destructive (contained) |
Visual anchor cho error section |
— |
| Soft status — "3 warnings" count |
warning-muted |
Background-level notification |
❌ warning solid — too aggressive |
| Success confirmation — "Payment complete" |
success (contained) |
Celebration moment, high emphasis |
— |
| Ongoing status — "Connected", "Active" |
success-muted |
Persistent indicator, shouldn't demand attention |
❌ success solid — too loud for always-on |
| Neutral / disabled context |
muted |
Visual placeholder, category separator |
— |
| Info / help icon |
info-muted |
Gentle cue, not commanding |
❌ info solid — too prominent |
Decision rule: Solid = one-time emphasis, CTA, confirmation. Muted = persistent, informational, repeated list items.
10.4. Size selection
| Context |
Size |
Container |
When |
| Inline badges, compact lists, mobile nav |
xs |
24px |
Tight space, icon supplementary |
| iOS Settings rows, standard list items |
sm |
28px |
Most common list usage |
| Default — card headers, section markers |
md |
32px |
General-purpose |
| Feature cards, KPI cards, dashboard headers |
lg |
40px |
Icon = primary visual element |
| Hero sections, empty states, onboarding |
xl |
48px |
Maximum emphasis, icon-first |
Consistency rule: Cùng một list group → PHẢI dùng cùng size. KHÔNG mix sizes trong cùng list.
11. States
Lead Icon là decorative component — KHÔNG có interactive states nội tại.
| Thuộc tính |
Giá trị |
Lý do |
| Hover |
❌ Không có |
Icon decorative, interaction thuộc về parent item |
| Focus |
❌ Không có |
Không focusable, parent nhận focus |
| Disabled |
❌ Không có |
Parent item quyết định disabled state: opacity: var(--disabled) cascade xuống icon |
| Pressed |
❌ Không có |
Parent item display pressed state |
| Transition |
✅ background, color |
Hỗ trợ smooth color shift khi parent thay đổi context (e.g., theme switch) |
Nếu icon CẦN click riêng → Wrap trong <button> hoặc <a>, KHÔNG thêm interactive states vào .ds-leadicon.
12. Do / Don't
| ✅ DO |
❌ DON'T |
Rule |
Dùng primary-muted cho repeated list items |
Dùng primary solid cho mỗi row → quá overwhelming |
§1 C7: max 3 accent |
| Dùng cùng size cho tất cả items trong 1 list |
Mix sm + lg trong cùng list → visual chaos |
Best Practice §7 |
Dùng naked cho action/flat lists |
Dùng contained cho mọi icon → clutter |
NNG H8 |
Dùng square cho iOS Settings style |
Dùng circle cho iOS Settings → off-brand |
Apple HIG |
Wrap trong <button> nếu icon clickable |
Thêm cursor: pointer trực tiếp lên .ds-leadicon |
§5 B1 |
aria-hidden="true" khi text label adjacent |
Bỏ qua ARIA → SR đọc icon + text, duplicate info |
§7 F2 |
| Dùng Lucide icons only |
Dùng emoji, Font Awesome, external icons → inconsistent stroke |
Best Practice §7 |
Dùng destructive naked + red text cho Delete |
Dùng destructive-muted cho destructive action → mất urgency |
§1 Visual Hierarchy |
flex-shrink: 0 trên cả container + SVG |
Để icon co lại khi text dài → ellipsis text nhưng icon bị méo |
Layout rule |
Dùng success-muted cho persistent "Online" status |
Dùng success solid cho always-on → too attention-grabbing |
NNG H8 |
13. Content Guidelines — Icon Choice
Stroke style
- LUÔN dùng Lucide stroke icons — từ
assets/icons/
- KHÔNG dùng filled icons — filled icons clash với muted bg (không đủ contrast khi icon + bg cùng color family)
- Exception:
circle, square, triangle — geometric shapes OK filled
Icon meaning
- Icon phải self-explanatory OR có text label adjacent (C4: color alone không đủ)
- Mỗi icon chỉ đại diện 1 concept — không reuse cùng icon cho 2 ý nghĩa khác nhau trong cùng screen
- Ưu tiên metaphor phổ biến:
trash = delete, settings = gear, wifi = signal, bell = notification
Sizing consistency
- Container-to-icon ratio luôn giữ consistent: container ≈ 1.3–1.6× icon
- Icon inner size tự scale theo size preset — KHÔNG override inner icon size manually