Live Preview
Primary
Success
Warning
Error
Info
Outline
--- description: Hướng dẫn Agent tự động tạo UI Component Badge/Tag/Chip dựa trên Design Tokens, có ngữ nghĩa chuẩn Material 3 & iOS HIG
Badge Component Generation Skill
Skill này hướng dẫn bạn (AI Agent) tạo component Badge / Tag / Chip — nhãn nhỏ hiển thị trạng thái, danh mục, hoặc số đếm.
1. Mục tiêu (Objective)
Tạo component Badge đa năng: hiển thị status label, counter (notification count), tag cho categorization, chip có thể xoá. Tích hợp 100% semantic color tokens.
2. AI Context & Intent (Ngữ cảnh cho AI)
Khi nào dùng Badge?
- Hiển thị trạng thái: "Active", "Pending", "Expired"
- Counter / Notification dot: Số unread messages, notification count
- Category tag: Nhãn phân loại ("Frontend", "Backend", "Design")
- Selectable chip: Tag có thể thêm/xoá (vd: filter tags)
Phân biệt Badge / Tag / Chip
| Tên | Mục đích | Interactive? |
|---|---|---|
| Badge | Status label, counter | ❌ Read-only |
| Tag | Category, taxonomy | ❌ Read-only hoặc ✅ removable |
| Chip | Filter, selection | ✅ Selectable / removable |
Decision Tree cho AI
text
Cần hiển thị label nhỏ?
├─ Status / trạng thái → Badge (variant theo severity)
├─ Notification count → Badge (counter mode)
├─ Notification dot (không số) → Badge (dot mode)
├─ Category / phân loại → Tag
├─ Filter có thể xoá → Chip (removable)
└─ Selection toggle → Chip (selectable)
3. Ngữ nghĩa & Phân loại (Semantics)
3.1. Variant theo Severity / Semantic
| Variant | Mục đích | Token BG | Token Text |
|---|---|---|---|
default |
Neutral info | base.muted |
base.foreground |
primary |
Brand accent | base.primary-muted |
base.primary-muted-foreground |
secondary |
Secondary brand | base.secondary-muted |
base.secondary-muted-foreground |
success |
Positive status | base.success-muted |
base.success-muted-foreground |
warning |
Caution | base.warning-muted |
base.warning-muted-foreground |
destructive |
Error / danger | base.destructive-muted |
base.destructive-muted-foreground |
info |
Informational | base.info-muted |
base.info-muted-foreground |
outline |
Subtle, bordered | transparent |
base.foreground + base.border |
3.2. Mode
| Mode | Mô tả |
|---|---|
| Label | Text badge (mặc định) — "Active", "New" |
| Counter | Số đếm — "3", "99+" (compact oval) |
| Dot | Chấm tròn nhỏ, không text — notification indicator |
3.3. Size
- sm:
font.size.xs(12px), padding minimal - md:
font.size.sm(14px), padding cân đối
3.4. Slot Map (Figma ↔ Code)
📎 Source:
slot-manifest.json→badge· Layer: item
| Figma Slot | data-slot |
CSS Class | Required | Accepts |
|---|---|---|---|---|
| Root | badge |
.badge |
✅ | — |
| Icon | badge-icon |
— | ❌ | icon |
| Label | badge-label |
— | ✅ | text, number |
4. Token Mapping
📦 Token values: Xem
ATOMIC-MAPPING.md— single source of truth cho tất cả actual token values.
| Token | Type | Value | Mô tả |
|---|---|---|---|
padding-x.sm |
number | {spacing.1-5} |
Horizontal padding for small badge |
padding-x.md |
number | {spacing.2-5} |
Horizontal padding for medium badge |
padding-y.sm |
number | {spacing.0-5} |
Vertical padding for small badge |
padding-y.md |
number | {spacing.1} |
Vertical padding for medium badge |
font-size.sm |
number | {font.size.xs} |
Small badge text |
font-size.md |
number | {font.size.sm} |
Medium badge text |
font-weight |
number | {font.weight.medium} |
Badge label weight |
radius |
number | {border-radius.full} |
chip shape |
dot-size |
number | {spacing.2} |
Notification dot diameter |
close-icon-size |
number | {spacing.3} |
Remove button size for chip mode |
gap |
number | {spacing.1} |
Gap between icon and text |
color.default-bg |
color | {base.muted} |
|
color.default-fg |
color | {base.foreground} |
|
color.primary-bg |
color | {base.primary-muted} |
|
color.primary-fg |
color | {base.primary-muted-foreground} |
|
color.secondary-bg |
color | {base.secondary-muted} |
|
color.secondary-fg |
color | {base.secondary-muted-foreground} |
|
color.success-bg |
color | {base.success-muted} |
|
color.success-fg |
color | {base.success-muted-foreground} |
|
color.warning-bg |
color | {base.warning-muted} |
|
color.warning-fg |
color | {base.warning-muted-foreground} |
|
color.destructive-bg |
color | {base.destructive-muted} |
|
color.destructive-fg |
color | {base.destructive-muted-foreground} |
|
color.info-bg |
color | {base.info-muted} |
|
color.info-fg |
color | {base.info-muted-foreground} |
|
color.outline-border |
color | {base.border} |
|
color.close-hover |
color | {state-layer.hover} |
|
transition |
string | {duration.fast-2} {easing.standard} |
Default interaction transition |
5. Props & API
typescript
interface BadgeProps {
/** Semantic variant */
variant?: 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'destructive' | 'info' | 'outline';
/** Display mode */
mode?: 'label' | 'counter' | 'dot';
/** Size */
size?: 'sm' | 'md';
/** Content — text hoặc number */
children?: ReactNode;
/** Max count (counter mode) — vượt quá hiển thị "99+" */
maxCount?: number;
/** Left icon */
icon?: ReactNode;
/** Removable — hiện nút close (chip mode) */
removable?: boolean;
/** On remove callback */
onRemove?: () => void;
}
6. Accessibility (a11y)
- Role: Badge read-only là
<span>, không cần role đặc biệt. - Counter: Dùng
aria-labelmô tả context (vd:aria-label="3 unread messages"). - Removable (chip): Nút close phải có
aria-label="Remove [tag name]". - Dot: Badge dot BẮT BUỘC có
aria-labelvì không có text visible. - Color không đủ: Không chỉ dùng màu sắc để truyền tải thông tin — kết hợp icon hoặc text.
7. Best Practices & Rules
- Không interactive (Badge/Tag): Không có hover/click effect, chỉ hiển thị thông tin.
- Counter max: Khi giá trị >
maxCount(mặc định 99), hiển thị "99+". - Dot position: Khi dùng như notification dot overlapping element khác, dùng absolute positioning.
- Không Hardcode: Mọi giá trị từ Token.
- Semantic color: LUÔN chọn variant phù hợp ngữ nghĩa —
successcho trạng thái tốt,destructivecho lỗi... - Icon: Close/remove icon (
x) và leading icon CHỈ dùng Lucide icon từassets/icons/. CẤM dùng text emoji. Xemicon.mdmục 10.
8. Example Usage
jsx
{/* Status badges */}
<Badge variant="success">Active</Badge>
<Badge variant="warning">Pending</Badge>
<Badge variant="destructive">Expired</Badge>
{/* Counter */}
<Badge variant="destructive" mode="counter" maxCount={99}>150</Badge>
{/* → Hiển thị "99+" */}
{/* Dot notification */}
<Badge mode="dot" variant="destructive" />
{/* Removable tag/chip */}
<Badge variant="primary" removable onRemove={handleRemove}>
Frontend
</Badge>