Prisma
Live Preview

Checkbox Component Generation Skill

Skill này hướng dẫn bạn (AI Agent) tạo component Checkbox — điều khiển cho phép chọn nhiều giá trị, hỗ trợ trạng thái indeterminate.

1. Mục tiêu (Objective)

Tạo component Checkbox hoàn chỉnh gồm Checkbox đơn lẻ và Checkbox Group, hỗ trợ indeterminate state cho "Select All", tích hợp 100% Design Tokens.

2. AI Context & Intent (Ngữ cảnh cho AI)

Khi nào dùng Checkbox?

  • Chọn nhiều giá trị từ nhóm options (vd: chọn tính năng, chọn danh mục)
  • Toggle đơn lẻ cho agree/consent (vd: "Tôi đồng ý điều khoản")
  • Select All / Deselect All trong danh sách

Phân biệt với component khác

Tình huống Component đúng Lý do
Chọn NHIỀU từ ≤ 5 options Checkbox Group Thấy hết, toggle nhanh
Chọn NHIỀU từ > 5 options Select (multi) Tiết kiệm không gian
Chọn MỘT từ ≤ 5 options Radio Group Mutually exclusive
Toggle on/off có hiệu lực TỨC THÌ Switch Instant effect, no save
Toggle on/off trong form (cần submit) Checkbox Deferred, submit cùng form

Decision Tree cho AI

text
User cần toggle/chọn?
├─ Nhiều lựa chọn cùng lúc → Checkbox (Group)
├─ Một lựa chọn duy nhất trong nhóm → Radio
├─ On/Off tức thì (không cần save) → Switch
├─ On/Off trong form (cần save/submit) → Checkbox (đơn lẻ)
└─ Agree/consent/terms → Checkbox (đơn lẻ)

3. Ngữ nghĩa & Phân loại (Semantics)

3.1. Checkbox States

State Visual Mô tả
Unchecked Chưa chọn, hiện border box trống
Checked Đã chọn, hiện check icon + background primary
Indeterminate ☐─ Một phần con đã chọn (dùng cho "Select All")
Disabled ☐ (mờ) Không tương tác, giảm opacity
Error ☐ (đỏ) Validation thất bại (vd: chưa agree terms)

3.2. Checkbox Group

  • Wrapper chứa nhiều Checkbox với label, mô tả, error chung.
  • Hỗ trợ orientation: vertical (mặc định) hoặc horizontal.
  • Có thể có "Select All" checkbox với indeterminate logic tự động.

3.5. Slot Map (Figma ↔ Code)

📎 Source: slot-manifest.jsoncheckbox · Layer: item

Figma Slot data-slot CSS Class Required Accepts
Root checkbox .checkbox
Indicator checkbox-indicator checkmark
Label checkbox-label text
Description checkbox-description 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ả
box-size number {spacing.5} Checkbox box dimensions (20px)
box-radius number {comp-radius-small} Rounded square (8px web/mobile)
gap number {spacing.2} Gap between checkbox and label
group-gap number {spacing.3} Gap between checkbox items in group
color.box-border color {base.input-border} Unchecked border
color.box-bg-unchecked color transparent Unchecked background
color.box-bg-checked color {base.primary} Checked fill
color.box-bg-indeterminate color {base.primary} Indeterminate fill
color.check-icon color {base.primary-foreground} Tick mark color
color.box-border-error color {base.destructive} Error border
color.label color {base.foreground} Label text
color.description color {base.muted-foreground} Description text below label
color.hover color {state-layer.hover} Box hover background
color.focus-ring color {focus.ring-color} Focus ring color — ref shared/focus
color.bg color {base.background} Default background
disabled-opacity number {opacity.50}
transition string {duration.instant} {easing.standard} Check/uncheck animation
padding number {item.padding-default} Internal padding

5. Props & API

typescript
interface CheckboxProps {
  /** Checked state */
  checked?: boolean;
  /** Indeterminate state (overrides checked visual) */
  indeterminate?: boolean;
  /** Label text */
  label?: string;
  /** Description bên dưới label */
  description?: string;
  /** Disabled */
  disabled?: boolean;
  /** Error state */
  isError?: boolean;
  /** Size */
  size?: 'sm' | 'md' | 'lg';
  /** onChange callback */
  onChange?: (checked: boolean) => void;
}

interface CheckboxGroupProps {
  /** Label của group */
  label?: string;
  /** Options */
  options: { value: string; label: string; description?: string; disabled?: boolean }[];
  /** Values đã chọn */
  value?: string[];
  /** Orientation */
  orientation?: 'vertical' | 'horizontal';
  /** Error message */
  errorMessage?: string;
  /** Select All option */
  showSelectAll?: boolean;
  /** onChange callback */
  onChange?: (values: string[]) => void;
}

6. Accessibility (a11y)

  • Role: Dùng <input type="checkbox"> native (có thể ẩn visually).
  • Label: Mỗi checkbox phải có <label> kết nối qua htmlFor.
  • Indeterminate: Set checkbox.indeterminate = true qua JavaScript (không có HTML attribute).
  • Group: Wrap trong <fieldset> + <legend> hoặc role="group" + aria-labelledby.
  • Keyboard: Space toggle checked, Tab di chuyển focus giữa checkboxes.
  • Error: aria-invalid="true" + aria-describedby trỏ error message.

7. Best Practices & Rules

  • Semantic HTML: Dùng native <input type="checkbox">, có thể custom visual bằng CSS.
  • Touch target: Vùng bấm tối thiểu 44×44px (iOS) — bao gồm cả label area.
  • Indeterminate logic: Khi "Select All" checked → tất cả con checked. Khi bỏ → tất cả unchecked. Khi một phần → indeterminate.
  • Không Hardcode: Mọi giá trị từ Token.
  • Icon: Check mark (check), indeterminate dash (minus) CHỈ dùng Lucide icon từ assets/icons/. CẤM dùng text emoji. Xem icon.md mục 10.

8. Example Usage

jsx
{/* Single checkbox */}
<Checkbox label="Tôi đồng ý với Điều khoản sử dụng" />

{/* Checkbox group */}
<CheckboxGroup
  label="Chọn tính năng"
  showSelectAll
  options={[
    { value: 'qr', label: 'QR Pay', description: 'Thanh toán bằng mã QR' },
    { value: 'nfc', label: 'NFC', description: 'Thanh toán chạm' },
    { value: 'card', label: 'Thẻ liên kết' },
  ]}
  value={['qr', 'nfc']}
/>

{/* Error state */}
<Checkbox label="Tôi đồng ý" isError />