Prisma
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.jsontoggle-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) or role="radiogroup" (single).
  • Items: role="radio" (single) or role="checkbox" (multiple), aria-checked.
  • Keyboard: Arrow Left/Right navigates, Space/Enter selects.

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>