Live Preview
--- description: Hướng dẫn Agent tạo Toggle Group / Segmented Control — inline option switcher
Toggle Group / Segmented Control
Skill này hướng dẫn tạo component Toggle Group — inline switcher cho 2-5 options, thay thế radio khi options ít và cần compact.
1. Mục tiêu (Objective)
Tạo Toggle Group — inline switcher cho 2-5 options, thay thế radio khi options ít và cần compact. Hỗ trợ single và multiple selection.
2. AI Context & Intent (Ngữ cảnh cho AI)
Khi nào dùng Toggle Group?
- View switcher: Grid/List/Map view toggle
- Period selector: Day/Week/Month/Year
- Format toggle: Light/Dark mode, Metric/Imperial
- Filter presets: All/Active/Completed
⚠️ Phân biệt Toggle Group vs Tabs vs Radio vs Select (QUAN TRỌNG)
| Tiêu chí | Toggle Group | Tabs | Radio Group | Select |
|---|---|---|---|---|
| Bản chất | Inline option switcher | Content panels | Form input | Dropdown |
| Options | 2-5 items | 2-7 tabs | 2-10 options | Unlimited |
| Visual | chip/contained buttons | Tab bar | Circles + labels | Dropdown list |
| Content change | Filter/view mode | Full panel swap | Form value | Form value |
| Ví dụ | Grid/List toggle | Settings panels | Gender selection | Country selector |
Decision Tree cho AI
text
Cần switch giữa options?
├─ Switch view/filter mode (2-5 options) → Toggle Group
│ ├─ Grid/List view → Toggle Group (icon + text)
│ ├─ Day/Week/Month → Toggle Group (text only)
│ └─ 2 options (on/off) → Toggle Group hoặc Switch
│
├─ Switch content panels → Tabs
│ ├─ Each tab has substantial content → Tabs
│ └─ Tab content is complex → Tabs
│
├─ Form field selection → Radio Group
│ ├─ 2-4 visible options → Radio Group
│ └─ Vertical layout → Radio Group
│
├─ Many options (5+) → Select / Dropdown
└─ Binary toggle → Switch
3. Anatomy
text
Default variant (sliding bg):
┌─────────────────────────────────────────┐
│ ┌────────┐ │ ← Container: --muted bg
│ │ Grid │ List Map │ ← Active: --card bg (raised)
│ └────────┘ │ ← Inactive: --muted-foreground
└─────────────────────────────────────────┘ --comp-radius
Outline variant:
┌─────────┬─────────┬─────────┐
│ Grid ✓ │ List │ Map │ ← Items with --border
└─────────┴─────────┴─────────┘ ← Active: filled bg --primary-muted
4. Platform Mapping
| Platform | Component | Key Difference |
|---|---|---|
| Web | Toggle Group (custom) | Background indicator sliding |
| iOS | UISegmentedControl | chip shape, system standard |
| Android (M3) | SegmentedButton | Outlined/filled, icon support |
| Fluent | ❌ (use TabList) | No dedicated component |
| Carbon | ContentSwitcher | Bordered buttons, no sliding |
Cross-platform note: Đây là HUB component — cùng UX intent nhưng visual rất khác giữa platforms.
Hub Validation
text
Use case: "Switch between 2-5 views inline"
Web → Toggle Group (sliding bg indicator)
iOS → SegmentedControl (chip, system native)
Android → SegmentedButton (outlined, icon optional)
Carbon → ContentSwitcher (bordered buttons)
5. Variants
| Variant | Mô tả |
|---|---|
default |
Background container + raised active |
outline |
Bordered items, filled active |
ghost |
No container, underline active |
5.4. Slot Map (Figma ↔ Code)
📎 Source:
slot-manifest.json→toggle-group· Layer: item
| Figma Slot | data-slot |
CSS Class | Required | Accepts |
|---|---|---|---|---|
| Root | toggle-group |
.toggle-group |
✅ | — |
| Item | toggle-group-item |
.toggle-group-item |
✅ (n×) | text, icon, icon+text |
6. Token Mapping
📦 Atomic Mapping: Xem
ATOMIC-MAPPING.md→ mục toggle-group — Density Tier: comp.Container bg dùng
--muted, active bg dùng--card, active fg dùng--foreground, inactive fg dùng--muted-foreground. Component token JSON files đã deprecated.
7. Props & API
typescript
interface ToggleGroupProps {
value?: string | string[];
type?: 'single' | 'multiple';
variant?: 'default' | 'outline' | 'ghost';
size?: 'sm' | 'md' | 'lg';
fullWidth?: boolean;
onChange: (value: string | string[]) => void;
children: ReactNode;
}
interface ToggleGroupItemProps {
value: string;
label: string;
icon?: ReactNode;
disabled?: boolean;
}
8. Accessibility (a11y)
- Container:
role="group"(multiple) orrole="radiogroup"(single). - Items:
role="radio"(single) orrole="checkbox"(multiple),aria-checked. - Keyboard:
Arrow Left/Rightnavigates,Space/Enterselects.
9. Best Practices & Rules
- Max 5 items: More → use Tabs or Select/Dropdown.
- Equal width: Items stretch equally by default.
- Icon + text: Combine for clarity, icon-only with tooltip for compact.
- Single vs Multiple: Default single-select. Multiple only when options are independent.
- Không Hardcode: Mọi giá trị từ Token.
10. Example Usage
jsx
{/* View mode toggle */}
<ToggleGroup value={viewMode} onChange={setViewMode}>
<ToggleGroupItem value="grid" label="Grid" icon="grid" />
<ToggleGroupItem value="list" label="List" icon="list" />
<ToggleGroupItem value="map" label="Map" icon="map" />
</ToggleGroup>
{/* Period selector */}
<ToggleGroup value={period} onChange={setPeriod} variant="outline">
<ToggleGroupItem value="day" label="Day" />
<ToggleGroupItem value="week" label="Week" />
<ToggleGroupItem value="month" label="Month" />
<ToggleGroupItem value="year" label="Year" />
</ToggleGroup>
{/* Multi-select filter */}
<ToggleGroup value={filters} type="multiple" onChange={setFilters}>
<ToggleGroupItem value="active" label="Active" />
<ToggleGroupItem value="pending" label="Pending" />
<ToggleGroupItem value="resolved" label="Resolved" />
</ToggleGroup>