Live Preview
Notifications — On
Dark Mode — Off
Disabled (on)
--- description: Hướng dẫn Agent tự động tạo UI Component Switch/Toggle dựa trên Design Tokens, có ngữ nghĩa chuẩn Material 3 & iOS HIG
Switch Component Generation Skill
Skill này hướng dẫn bạn (AI Agent) tạo component Switch / Toggle — điều khiển bật/tắt có hiệu lực tức thì.
1. Mục tiêu (Objective)
Tạo component Switch hoàn chỉnh, thể hiện rõ trạng thái on/off, có animation mượt mà, hỗ trợ Dark Mode và tích hợp 100% Design Tokens.
2. AI Context & Intent (Ngữ cảnh cho AI)
Khi nào dùng Switch?
- Bật/tắt setting có hiệu lực TỨC THÌ (không cần nhấn Save)
- Trạng thái nhị phân rõ ràng: on/off, enable/disable, show/hide
⚠️ Phân biệt Switch vs Checkbox (QUAN TRỌNG)
| Tiêu chí | Switch | Checkbox |
|---|---|---|
| Hiệu lực | TỨC THÌ (instant) | SAU KHI submit form |
| Ngữ cảnh | Settings, toggles | Forms, agreements |
| Metaphor | Công tắc đèn | Danh sách đánh dấu |
| Ví dụ | Dark mode, Notifications | "Tôi đồng ý", chọn features |
| Tương đồng | Switch (Material 3 & iOS) |
Checkbox (Material 3) |
Decision Tree cho AI
text
User cần toggle on/off?
├─ Có hiệu lực tức thì (settings) → Switch
├─ Trong form, cần submit → Checkbox
├─ Chọn 1 từ 2+ options → Radio
└─ Chọn nhiều → Checkbox Group
3. Ngữ nghĩa & Phân loại (Semantics)
3.1. Switch States
| State | Track | Thumb | Mô tả |
|---|---|---|---|
| Off | base.muted |
color-base.white |
Tắt, mờ |
| On | base.primary |
color-base.white |
Bật, highlight |
| Disabled Off | base.muted (faded) |
color-base.white (faded) |
Không tương tác |
| Disabled On | base.primary (faded) |
color-base.white (faded) |
Khoá ở trạng thái bật |
🎯 Best Practice: Thumb LUÔN trắng (#ffffff) ở mọi state — theo chuẩn iOS HIG, Material Design 3, shadcn/ui, Ant Design, và Carbon IBM.
3.2. Size Variants
- sm: Compact, dùng trong dense lists, tables.
- md: Default, dùng trong settings pages.
- lg: Prominent, dùng khi cần emphasis.
3.5. Slot Map (Figma ↔ Code)
📎 Source:
slot-manifest.json→switch· Layer: item
| Figma Slot | data-slot |
CSS Class | Required | Accepts |
|---|---|---|---|---|
| Root | switch |
.switch |
✅ | — |
| Thumb | switch-thumb |
— | ✅ | — |
| Label | switch-label |
— | ❌ | text |
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ả |
|---|---|---|---|
track-width.sm |
number | {min-width.9} |
Small track width |
track-width.md |
number | {min-width.11} |
Default track width |
track-width.lg |
number | 52 |
Large track width |
track-height.sm |
number | {min-width.5} |
Small track height |
track-height.md |
number | {min-width.6} |
Default track height |
track-height.lg |
number | {min-width.7} |
Large track height |
thumb-size.sm |
number | {min-width.4} |
Small thumb size |
thumb-size.md |
number | {min-width.5} |
Default thumb size |
thumb-size.lg |
number | {min-width.6} |
Large thumb size |
radius |
number | {border-radius.full} |
chip shape |
label-gap |
number | {spacing.2} |
Gap giữa switch và label |
color.track-off |
color | {base.muted} |
Track bg khi off |
color.track-on |
color | {base.primary} |
Track bg khi on |
color.thumb |
color | {color-base.white} |
Thumb color — luôn trắng (iOS/MD3/shadcn standard) |
color.hover |
color | {state-layer.hover} |
Hover state layer |
color.focus-ring |
color | {focus.ring-color} |
Focus ring — ref shared/focus |
color.bg |
color | {base.background} |
Default background |
color.fg |
color | {base.foreground} |
Default foreground |
thumb-shadow |
shadow | {shadow.xs} |
Subtle thumb drop shadow |
disabled-opacity |
number | {opacity.50} |
Disabled opacity |
transition |
string | {duration.normal-1} {easing.standard} |
Thumb slide animation |
padding |
number | {item.padding-default} |
Internal padding |
5. Props & API
typescript
interface SwitchProps {
/** Checked state */
checked?: boolean;
/** Default checked (uncontrolled) */
defaultChecked?: boolean;
/** Label — hiển thị bên phải switch */
label?: string;
/** Description — text phụ dưới label */
description?: string;
/** Size */
size?: 'sm' | 'md' | 'lg';
/** Disabled */
disabled?: boolean;
/** On change callback */
onChange?: (checked: boolean) => void;
}
6. Accessibility (a11y)
- Role: Dùng
<button role="switch">hoặc<input type="checkbox" role="switch">. - State:
aria-checked="true"/"false"(KHÔNG dùngaria-pressed). - Label: Liên kết qua
aria-labelledbyhoặcaria-label. - Keyboard:
Space/Entertoggle. - Focus:
:focus-visibleoutline rõ ràng. - Screen reader: Announce "on" / "off" khi toggle.
7. Best Practices & Rules
- Instant effect: Switch PHẢI có hiệu lực ngay khi toggle — nếu cần save, dùng Checkbox.
- Label position: Label mặc định bên phải switch (LTR). Support RTL nếu cần.
- Animation: Thumb slide smooth (200ms ease), KHÔNG snap ngay.
- Không dùng text "ON/OFF" trên track — sử dụng màu sắc đủ rõ ràng.
- Không Hardcode: Mọi giá trị từ Token.
8. Example Usage
jsx
{/* Basic */}
<Switch label="Chế độ tối" checked={isDark} onChange={setIsDark} />
{/* With description */}
<Switch
label="Thông báo"
description="Nhận thông báo qua email khi có giao dịch mới"
size="md"
/>
{/* Disabled */}
<Switch label="Tính năng Beta" disabled checked />