DataTable
Mẫu chuẩnBảng tương tác cho dữ liệu có phân trang. Table vẫn chỉ để đọc. DataTable thêm sắp xếp, chọn hàng, cột và trạng thái tải — không tự fetch.
Playground
Đổi brand, theme và trạng thái. Khung bảng lấy đúng bề rộng cột nội dung; cột dư cuộn bên trong, không đẩy trang ngang.
Sẵn sàng. Chọn hàng để thấy số id. Sắp xếp, cột và phân trang nằm trong khung bảng.
import { DropdownMenuItem } from "@nexobox/ui";
import { DataTable, DataTableRowMenu, type DataTableColumn } from "@nexobox/ui/data-table";
<DataTable
columns={columns}
data={rows}
getRowId={(row) => row.id}
label="Khách hàng"
selectable
rowActions={(row) => (
<DataTableRowMenu label={"Thao tác " + row.name}>
<DropdownMenuItem>Xem hồ sơ</DropdownMenuItem>
</DataTableRowMenu>
)}
/>Khi nào sử dụng
Nên dùng
Danh sách có cột, cần sắp xếp, chọn theo id ổn định, và phân trang 25, 50 hoặc 100 hàng.
Khi nào không dùng
Tránh dùng
| Không dùng cho | Dùng thay |
|---|---|
| Bảng chỉ đọc, không sắp xếp, không chọn, không phân trang | Table |
| Danh sách thẻ không có quan hệ cột | Card |
Anatomy
Một vùng có nhãn. Khung lấy bề rộng của cha và cuộn phần cột dư bên trong. Shadow của header chỉ xuất hiện sau khi vùng đã cuộn dọc. Ô tiêu đề phủ kín ô. Nền header trùng màu ghost hover, nên hover chuyển sang ghost pressed. Vạch đổi rộng cột dùng màu focus và chỉ hiện dần khi hover đúng tay nắm, không hiện khi hover cả ô tiêu đề. Hàng dữ liệu có viền subtle; hàng chẵn nền nhạt hơn header một bậc. Nút cột nằm ở cuối hàng tiêu đề. Bảng cuộn ngang khi tổng bề rộng cột lớn hơn khung. Cỡ trang và nút trước/sau cao 36px.
| # | Phần | Ghi chú |
|---|---|---|
| 1 | Thanh công cụ | Chưa chọn thì hiện toolbar. Đang chọn thì hiện số id và nút bỏ chọn, cùng chỗ đó. |
| 2 | Nút cột | Ghost, chỉ icon, mở Popover bật tắt cột. Cột enableHiding: false không tắt được. |
| 3 | Header dính | Nằm trong vùng cuộn của Table. Nút sắp xếp phủ kín ô và mang aria-sort. |
| 4 | Tay nắm cột | Kéo để xem trước, thả thì ghi chiều rộng. Mũi tên trái và phải bước 16px. |
| 5 | Cột thao tác | Chỉ khi có rowActions. Dính bên phải. DataTableRowMenu là nút ⋯. |
| 6 | Chân trang | Select chọn 25, 50 hoặc 100. Pagination giữ nút trước và sau. |
Variants
chrome="card" là mặc định: khung có viền, bo góc và vùng cuộn theo maxHeight. chrome="plain" bỏ khung đó. Hàng chạy tới mép phần tử cha. Vùng cuộn là chính bảng: chiếm phần cao còn lại của cha, tiêu đề dính trong vùng đó, pager nằm dưới. maxHeight không áp dụng. Khi mọi hàng nằm trên một trang, pager không hiện — host để số lượng cạnh bộ lọc của mình. Sang trang thứ hai thì pager trở lại, không có thẻ.
mode="local" là mặc định: sắp xếp và phân trang trên dữ liệu đã nằm trong trình duyệt. mode="server" yêu cầu phân trang và sắp xếp điều khiển từ ngoài, cộng rowCount hoặc pageCount. Host cấp cột, dữ liệu và id. Lọc, phân quyền, fetch, huỷ request và xuất file không nằm trong composite.
States
Các trạng thái đứng yên bên dưới, theo brand và theme của playground. Chọn một hàng ở bảng sẵn sàng để thấy nền selected.
Chọn hàng dùng nền selected và đếm id. Lựa chọn giữ theo id khi đổi trang.
Alert và nút thử lại. Hàng đã có được giữ. Lỗi bỏ qua khoảng chờ skeleton.
Dưới 200 ms chưa có chỉ báo động. Skeleton hiện sau ngưỡng đó và giữ tối thiểu 300 ms. Sau 8 giây có câu chờ lâu, không có phần trăm.
Hàng cũ còn. Spinner cạnh câu đang cập nhật. Trong lúc chờ, chọn, sắp xếp và phân trang không đổi hàng cũ.
Reduced motion: skeleton, spinner và vạch đổi rộng cột đứng yên.
Bàn phím & trợ năng
API & triển khai
| Prop | Mặc định | Quy ước |
|---|---|---|
| data | bắt buộc | Hàng của trang hiện tại, hoặc toàn bộ khi mode local |
| columns | bắt buộc | Định nghĩa cột TanStack. Id cột ổn định |
| getRowId | bắt buộc | Id hàng ổn định, khoá của lựa chọn |
| label | bắt buộc | Tên trợ năng của vùng bảng |
| mode | local | server cần pagination, sorting và rowCount hoặc pageCount |
| loading | false | Chỉ báo tải. Không trì hoãn request |
| error | — | Câu lỗi. Có thì bỏ qua skeleton |
| onRetry | — | Nút thử lại khi có lỗi |
| emptyMessage | Không có dữ liệu phù hợp. | Hiện trong bảng khi không có hàng |
| selectable | false | Checkbox theo trang. Lựa chọn giữ giữa các trang |
| selectionScope | default | Đổi giá trị này để bỏ chọn |
| selectionActions | — | Nhận mảng id đã chọn |
| toolbar | — | Thanh công cụ khi chưa chọn hàng |
| chrome | card | plain bỏ khung; cuộn nằm trong bảng và chiếm phần cao còn lại của cha; ẩn pager khi còn một trang |
| rowActions | — | Có thì hiện cột ⋯ dính bên phải. Dùng DataTableRowMenu |
| maxHeight | min(65vh, 42rem) | Chiều cao vùng cuộn |
| columnSettings | true | false ẩn nút bánh răng "Cột hiển thị" ở góc phải tiêu đề -- cho bảng mà host không muốn người đọc tự ẩn/hiện cột (K8, apps/nexo-crew/.../knowledge/documents). Cột thao tác vẫn còn nếu có rowActions. |
Design tokens
Màu, tiêu điểm, khoảng cách và chuyển động dùng token bảng và token nền đã có. Không token dùng chung mới. Chữ giao diện 14px, metadata 12px. Chiều cao hàng theo token hàng của Table.
Do / Don't
Nên dùng
Id hàng ổn định. Phân trang server khi dữ liệu không nằm trọn trong trình duyệt. Memo cột và dữ liệu đã lọc. Đổi selectionScope khi đổi tenant hoặc bộ lọc.
Tránh dùng
Sắp một trang rồi gọi đó là sắp toàn cục. Chọn tất cả xuyên tập dữ liệu. Fetch bên trong DataTable.