Bỏ qua tới nội dung
Component / 016 / NEXOFRAME

Accordion

Mẫu chuẩn

Một danh sách các mục có thể mở/đóng để xem nội dung bên trong, mở/đóng tức thời.

Radix Accordionsingle & multiple5 brand themesLight & dark

Playground

Đổi brand, theme, type và trạng thái. Không có prop size, không có prop variant.

LIVE PREVIEW

Một danh sách các mục có thể mở/đóng để xem nội dung bên trong, dựng trên Radix Accordion.

Bấm một trigger, hoặc dùng Tab + Enter/Space để mở đóng. Mũi tên Lên/Xuống di chuyển giữa các trigger.

import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@nexobox/ui";

<Accordion type="single" collapsible defaultValue="item-1">
  <AccordionItem value="item-1">
    <AccordionTrigger>Accordion là gì?</AccordionTrigger>
    <AccordionContent>Một danh sách các mục có thể mở/đóng để xem nội dung bên trong, dựng trên Radix Accordion.</AccordionContent>
  </AccordionItem>
  <AccordionItem value="item-2">
    <AccordionTrigger>Có animation khi mở không?</AccordionTrigger>
    <AccordionContent>Không. Repo chưa có token --nf-motion-accordion-*, nên mở/đóng tức thời.</AccordionContent>
  </AccordionItem>
</Accordion>

Khi nào sử dụng

Nên dùng

Nội dung dài, phân mảnh thành nhiều phần, mà người đọc chỉ cần xem một phần mỗi lúc: FAQ, các phần tuỳ chọn nâng cao trong một biểu mẫu, chi tiết bổ sung của từng hàng trong danh sách.

Tránh dùng

Các khung nhìn ngang hàng mà người dùng so sánh qua lại — đó là Tabs. Giấu nội dung then chốt mà ai cũng phải đọc. Một khối duy nhất chỉ cần bật/tắt hiển thị — đó là Collapsible, và @nexobox/ui chưa bọc primitive này.

Anatomy

#PhầnGhi chú
1AccordionAccordionPrimitive.Root. Giữ state, quyết định type single/multiple.
2AccordionItemMột hàng. Viền dưới --nf-semantic-border-subtle, không nền, không bo góc.
3AccordionTriggerTự bọc trong AccordionPrimitive.Header — Radix yêu cầu Header là cha trực tiếp của Trigger. Render h3. Cao 48 px ở comfortable, tăng lên 44 px ở compact — chiều duy nhất trong kit đi ngược hướng density, vì trigger là tiêu đề của cả một vùng chứ không phải một mục trong danh sách (DS-017 clause 8).
4ChevronArrowDown01Icon qua Icon của package, cuối trigger, xoay 180° khi data-state=open, aria-hidden.
5AccordionContentNội dung mở ra. Không portal — nằm tại chỗ trong cây DOM.

Variants & states

Không có variant. Không có size. Không có animation khi mở/đóng — repo chưa có token --nf-motion-accordion-*. Loading, error, empty: không có, Accordion không bất đồng bộ.

COLLAPSED

Trigger hiện, Content không render trong cây trợ năng.

EXPANDED

Chevron đã xoay 180°, Content hiện.

data-state=open trên trigger, chevron xoay 180°, Content hiện.

HOVER

Di chuyển chuột thật vào trigger để xem hover — nền đổi thành --nf-component-accordion-trigger-hover.

PRESSED

Giữ chuột thật xuống để xem pressed — nền đổi thành --nf-component-accordion-trigger-pressed. Không co scale — DS-018 rút press-scale khỏi mọi primitive.

FOCUS-VISIBLE

Outline theo --nf-component-focus-*, offset riêng. Ảnh mô phỏng bằng class xem trước, không phải Tab thật.

DISABLED

Cursor not-allowed, chữ đổi màu --nf-component-button-disabled-foreground.

Design tokens

Giá trị theo NexoCrew / light đang chọn trong playground. Item đọc --nf-semantic-border-subtle. Trigger đọc --nf-component-accordion-trigger-height, -trigger-hover, -trigger-pressed, -trigger-padding-block, -trigger-gap — alias riêng của Accordion, không còn bind thẳng --nf-foundation-size-* — cộng --nf-semantic-text-primary, --nf-component-focus-color, --nf-component-focus-width, --nf-component-focus-offset, --nf-component-button-disabled-foreground. Content đọc --nf-semantic-text-secondary và --nf-component-accordion-content-padding. Vẫn không tồn tại --nf-motion-accordion-* — mở/đóng tức thời, không đổi trong đợt này.

API & triển khai

PropMặc địnhQuy ước
type—Bắt buộc. "single" | "multiple".
value—Chế độ controlled. string khi single, string[] khi multiple.
defaultValue—Chế độ uncontrolled.
onValueChange—Phát khi tập mục mở đổi.
collapsiblefalseChỉ có nghĩa khi type="single". Mục đang mở có đóng lại được không.
disabledfalseTrên Root: khoá toàn bộ. Trên Item hoặc Trigger: khoá riêng một mục.
orientation"vertical"Hướng điều hướng bằng phím mũi tên.
dir—Hướng đọc "ltr" | "rtl".

Các type trên là ComponentPropsWithoutRef của Radix nên asChild, id, className, style truyền thẳng xuống phần tử tương ứng.

Accessibility & nội dung

Mỗi trigger là một điểm dừng Tab riêng — Accordion không dùng roving tabindex như Tabs.
Enter hoặc Space mở hoặc đóng trigger đang focus.
Mũi tên Lên/Xuống di chuyển focus giữa các trigger, Home/End về trigger đầu/cuối.
Trigger nằm trong h3 do AccordionPrimitive.Header dựng — cấu trúc heading trên trang phải hợp lý với heading bao ngoài.
Nội dung đang đóng không nằm trong cây trợ năng.