Prisma
Live Preview
Is it accessible?
Yes. It adheres to the WAI-ARIA design pattern for accordions.
Yes. It uses design tokens from the design system, ensuring consistency.
Yes. It supports smooth transitions when toggling open/closed states.

--- description: Hướng dẫn Agent tự động tạo UI Component Accordion/Collapsible dựa trên Design Tokens, có ngữ nghĩa chuẩn Material 3 & iOS HIG

Accordion Component Generation Skill

Skill này hướng dẫn bạn (AI Agent) tạo component Accordion / Collapsible — thu gọn và mở rộng nội dung theo section.

1. Mục tiêu (Objective)

Tạo component Accordion hỗ trợ single/multiple expand, smooth animation, và tích hợp 100% Design Tokens.

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

Khi nào dùng Accordion?

  • FAQ: Câu hỏi thường gặp, ẩn câu trả lời
  • Settings groups: Nhóm cài đặt có thể thu gọn
  • Long content: Chia content dài thành sections có thể collapse
  • Sidebar navigation: Menu các cấp có thể mở/đóng

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

Tình huống Component đúng Lý do
Ẩn/hiện content theo section Accordion Collapse/expand
Chuyển đổi content views Tabs Switch, không collapse
Show/hide 1 block đơn lẻ Collapsible (single Accordion) Simpler
Chi tiết item trong list Expandable Row / Disclosure Inline expand
Popup content Modal / Popover Overlay

Decision Tree cho AI

text
Cần ẩn/hiện nội dung?
├─ Nhiều sections, xếp dọc → Accordion
│   ├─ Chỉ 1 section mở tại 1 thời điểm → type="single"
│   └─ Nhiều sections mở cùng lúc → type="multiple"
├─ 1 block duy nhất ẩn/hiện → Collapsible (single AccordionItem)
├─ Chuyển view khác nhau → Tabs
└─ Content popup → Modal / Popover

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

3.1. Behavior Types

Type Mô tả
single Chỉ 1 item mở tại 1 thời điểm (mở cái mới → đóng cái cũ)
multiple Nhiều items mở cùng lúc

3.2. Visual Variants

Variant Mô tả
default Border bottom giữa items, nền transparent
bordered Mỗi item có border box riêng, gap giữa items
filled Active item có background highlight

3.3. Item States

State Mô tả Visual
Collapsed Nội dung ẩn Chevron → phải/xuống
Expanded Nội dung hiện Chevron → xuống, rotate 180°
Disabled Không thể toggle Opacity giảm

3.4. Slot Map (Figma ↔ Code)

📎 Source: slot-manifest.jsonaccordion · Layer: card

Figma Slot data-slot CSS Class Required Accepts
Root accordion .accordion
Item accordion-item .accordion-item ✅ (n×)
Trigger accordion-trigger .accordion-header text + chevron-icon
Content accordion-content .accordion-content typography, list, input-group, *

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ả
header-padding-y number {item.padding-default} Vertical padding header trigger
header-padding-x number 0 Horizontal padding (0 flush, có padding cho bordered)
content-padding number {item.padding-default} Content area padding
gap-bordered number {spacing.2} Gap giữa items (bordered variant)
radius number {item.radius} Border radius cho bordered variant
header-font-size number {font.size.sm} Header trigger text size
header-font-weight number {font.weight.medium} Header trigger text weight
content-font-size number {font.size.sm} Content body text size
chevron-size number {min-width.5} Chevron icon size
color.header-background color transparent Default variant header bg
color.header-background-hover color {state-layer.hover} Header hover state
color.header-background-filled color {base.muted} Filled variant expanded bg
color.header-text color {base.foreground} Header text color
color.chevron color {base.muted-foreground} Chevron icon color
color.content-text color {base.foreground} Content text color
color.border color {base.border} Separator giữa items
color.border-bordered color {base.card-border} Border cho bordered variant
color.focus-ring color {focus.ring-color} Focus ring — ref shared/focus
transition string {duration.normal-2} {easing.standard} Height expand/collapse animation
disabled-opacity number {opacity.50} Opacity cho disabled items

5. Props & API

typescript
interface AccordionProps {
  /** Behavior type */
  type?: 'single' | 'multiple';
  /** Active item(s) — controlled */
  value?: string | string[];
  /** Default open item(s) — uncontrolled */
  defaultValue?: string | string[];
  /** Visual variant */
  variant?: 'default' | 'bordered' | 'filled';
  /** Collapsible — cho phép đóng tất cả (type=single) */
  collapsible?: boolean;
  /** onChange callback */
  onChange?: (value: string | string[]) => void;
  children: ReactNode;
}

interface AccordionItemProps {
  /** Unique value */
  value: string;
  /** Header trigger text */
  title: string;
  /** Sub-title / description trong header */
  subtitle?: string;
  /** Disabled */
  disabled?: boolean;
  /** Custom trigger icon (thay thế chevron) */
  icon?: ReactNode;
  /** Content */
  children: ReactNode;
}

6. Accessibility (a11y)

  • Trigger: <button> hoặc <h*> với <button> bên trong. aria-expanded="true"/"false".
  • Content: role="region", aria-labelledby="[trigger-id]".
  • Keyboard: Enter / Space toggle. Arrow Up/Down di chuyển giữa triggers. Home / End → first/last.
  • Heading: Trigger nên wrap trong <h*> tag phù hợp hierarchy trang.
  • Disabled: aria-disabled="true", skip khi keyboard navigate.

7. Best Practices & Rules

  • Animation: Smooth height transition (CSS max-height hoặc JS height). Respect prefers-reduced-motion.
  • Overflow: Content bên trong phải handle overflow đúng (không bị cắt khi animated).
  • Không Hardcode: Mọi giá trị từ Token.
  • Icon: Chevron expand/collapse (chevron-down) CHỈ dùng Lucide icon từ assets/icons/. CẤM dùng text emoji. Xem icon.md mục 10.
  • Default open: FAQ thường nên mở item đầu tiên mặc định.

8. Example Usage

jsx
{/* FAQ accordion */}
<Accordion type="single" collapsible defaultValue="q1">
  <AccordionItem value="q1" title="Làm sao để liên kết thẻ?">
    Vào Cài đặt → Thẻ liên kết → Thêm thẻ mới...
  </AccordionItem>
  <AccordionItem value="q2" title="Phí giao dịch là bao nhiêu?">
    Miễn phí cho giao dịch dưới 500.000đ...
  </AccordionItem>
  <AccordionItem value="q3" title="Làm sao để đổi mật khẩu?">
    Vào Cài đặt → Bảo mật → Đổi mật khẩu...
  </AccordionItem>
</Accordion>

{/* Settings, multiple open */}
<Accordion type="multiple" variant="bordered">
  <AccordionItem value="general" title="Cài đặt chung">...</AccordionItem>
  <AccordionItem value="security" title="Bảo mật">...</AccordionItem>
  <AccordionItem value="notifications" title="Thông báo">...</AccordionItem>
</Accordion>