Table
Mẫu chuẩnDữ liệu đọc theo cả hai chiều — hàng và cột cùng mang nghĩa. Tailwind thuần trên <table> HTML thật, không runtime mới.
Playground
Đổi brand, theme và dữ liệu để xem cùng một Table thích ứng với nhận diện và ngữ cảnh.
| Mã giao dịch | Khách hàng | Trạng thái | Số tiền | Ngày tạo |
|---|---|---|---|---|
| GD-4821 | Nguyễn Thị Lan | Hoàn tất | 1.250.000₫ | 12/09/2026 |
| GD-4820 | Trần Văn Minh | Đang xử lý | 480.000₫ | 12/09/2026 |
| GD-4819 | Lê Hoàng Phúc | Thất bại | 2.100.000₫ | 11/09/2026 |
| GD-4818 | Phạm Thu Hà | Hoàn tất | 915.000₫ | 11/09/2026 |
Mật độ trang hiện tại: Rộng (48px/hàng).
import { Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow } from "@nexobox/ui";
<Table>
<TableCaption>Giao dịch gần đây</TableCaption>
<TableHeader>
<TableRow>
<TableHead>Khách hàng</TableHead>
<TableHead>Trạng thái</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell>Nguyễn Thị Lan</TableCell>
<TableCell>Hoàn tất</TableCell>
</TableRow>
</TableBody>
</Table>Khi nào sử dụng
Dữ liệu đọc theo cả hai chiều — hàng và cột cùng mang nghĩa, và người dùng so sánh giữa các hàng. Danh sách giao dịch, người dùng, đơn hàng với nhiều thuộc tính cùng cấp.
Khi nào không dùng
Danh sách thẻ không có quan hệ cột — dùng Card lặp lại. Bố cục thuần layout không mang dữ liệu bảng — dùng CSS grid của trang. Bảng cần sắp xếp, chọn hàng, hoặc phân trang — dùng DataTable. Bậc Table không có cả ba, xem mục Variants.
Anatomy
| Mã giao dịch | Khách hàng | Trạng thái |
|---|---|---|
| GD-4821 | Nguyễn Thị Lan | Hoàn tất |
| GD-4820 | Trần Văn Minh | Đang xử lý |
border-subtle, bo card 12, cuộn ngang khi tràn2 TableCaption — mô tả bảng, đứng trên header3 TableHeader — nền header-background4 TableHead — cột tiêu đề, scope="col"5 TableRow — chiều cao đổi theo density6 TableCell — ô dữ liệu, bo none, đệm ngang --nf-component-table-cell-padding-inlineVariants
Không có. Table không nhận prop biến thể — một cách trình bày duy nhất cho mọi ngữ cảnh. Ba khả năng sau không có ở bậc này: sắp xếp cột (cần trạng thái hướng sort chưa đặc tả), chọn hàng (cần checkbox cột đầu và hành vi bàn phím chưa quyết), phân trang (component riêng — Pagination — không import vào đây, chỉ đi kèm trên cùng một trang danh sách).
Header dính — không có. Bật đúng cách cần theo dõi vị trí cuộn để chỉ hiện --nf-foundation-shadow-raised khi có nội dung cuộn bên dưới; không component nào khác trong gói này theo dõi cuộn bằng JS, và một sticky tĩnh cộng shadow luôn bật sẽ vi phạm điều kiện đó.
Hàng nhấn được — không có. Không hàng nào nhận press-scale hay outline tiêu điểm; hover chỉ đổi nền để dễ dò dòng, không đổi con trỏ.
States
| Khách hàng | Trạng thái |
|---|---|
| Nguyễn Thị Lan | Hoàn tất |
| Trần Văn Minh | Đang xử lý |
Hàng thứ hai mô phỏng nền hover — không cần rê chuột thật để xem.
| Mã giao dịch | Khách hàng | Trạng thái | Số tiền | Ngày tạo |
|---|---|---|---|---|
| Không có giao dịch trong khoảng thời gian đã chọn. | ||||
Rỗng — một hàng, một ô colSpan bằng số cột. Không ẩn tbody.
Không có loading hay error ở bậc primitive: đó là trạng thái của vùng gọi Table, không phải của chính <table>.
| Khách hàng | Trạng thái |
|---|---|
| Nguyễn Thị Lan | Hoàn tất |
| Trần Văn Minh | Đang xử lý |
Rộng (comfortable) · --nf-component-table-row-height đo được: …
| Khách hàng | Trạng thái |
|---|---|
| Nguyễn Thị Lan | Hoàn tất |
| Trần Văn Minh | Đang xử lý |
Gọn (compact) · --nf-component-table-row-height đo được: …
Keyboard & accessibility
Design tokens
Giá trị theo NexoCRM / light đang chọn trong playground. Bề mặt đọc --nf-component-table-header-background, -row-background, -row-hover. Chiều cao hàng đọc --nf-component-table-row-height. Đệm ô đọc --nf-component-table-cell-padding-inline, caption đọc thêm -cell-padding-block. Khung đọc --nf-component-card-radius và --nf-semantic-border-subtle.
Kiểu chữ: --nf-foundation-typography-ui-* cho tiêu đề cột (0.875rem, weight 500). Ô dữ liệu cùng cỡ, weight 400. Số trong ô bind thêm vai data (tabular-nums). --nf-foundation-typography-caption-* cho caption.
API & triển khai
| Prop | Mặc định | Quy ước |
|---|---|---|
| Table.children | — | TableCaption, TableHeader, TableBody |
| Table.containerProps | — | Props của div cuộn bọc ngoài: ref, className, max-height, onScroll và nhãn vùng |
| *.className | — | Nối vào phần tử tương ứng, không thay thế |
| TableHead.scope | col | col | row | colgroup | rowgroup |
| TableCell.colSpan | — | Thuộc tính <td> gốc — dùng cho hàng rỗng |
Do / Don't
Nên dùng
- TableHead cho mọi ô tiêu đề cột
- Để chiều cao hàng theo density của vùng
- Render hàng rỗng thật khi không có dữ liệu
- Đặt Pagination cạnh Table như hai component độc lập
- Đặt nút/checkbox trong TableCell khi một ô thật sự cần bấm được
Tránh dùng
- TableCell trong thead — mất scope, AT không đọc được tên cột
- Đặt h-[...] cứng trên TableRow để ép một cỡ khác
- Ẩn tbody hoàn toàn khi rỗng
- Import Pagination bên trong table.tsx
- Gắn onClick lên TableRow để giả một hàng bấm được