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

DataTable

Mẫu chuẩn

Bả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.

Composite tầng 2TanStack TableTrang 25/50/100Không 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.

LIVE PREVIEW
Khách hàng
KH-0142Nguyễn Thị LanCần chú ý250.000₫
KH-0141Trần Văn MinhHoạt động500.000₫
KH-0140Lê Hoàng PhúcHoạt động750.000₫
KH-0139Phạm Thu HàHoạt động1.000.000₫
KH-0138Đỗ Gia HuyHoạt động1.250.000₫
KH-0137Võ Thanh TùngHoạt động1.500.000₫
KH-0136Bùi Ngọc AnhHoạt động1.750.000₫
KH-0135Hoàng Mai ChiCần chú ý2.000.000₫
KH-0134Nguyễn Thị LanHoạt động250.000₫
KH-0133Trần Văn MinhHoạt động500.000₫
KH-0132Lê Hoàng PhúcHoạt động750.000₫
KH-0131Phạm Thu HàHoạt động1.000.000₫
KH-0130Đỗ Gia HuyHoạt động1.250.000₫
KH-0129Võ Thanh TùngHoạt động1.500.000₫
KH-0128Bùi Ngọc AnhCần chú ý1.750.000₫
KH-0127Hoàng Mai ChiHoạt động2.000.000₫
KH-0126Nguyễn Thị LanHoạt động250.000₫
KH-0125Trần Văn MinhHoạt động500.000₫
KH-0124Lê Hoàng PhúcHoạt động750.000₫
KH-0123Phạm Thu HàHoạt động1.000.000₫
KH-0122Đỗ Gia HuyHoạt động1.250.000₫
KH-0121Võ Thanh TùngCần chú ý1.500.000₫
KH-0120Bùi Ngọc AnhHoạt động1.750.000₫
KH-0119Hoàng Mai ChiHoạt động2.000.000₫
KH-0118Nguyễn Thị LanHoạt động250.000₫
30 kết quả
Hàng / trang

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.

TSX
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 choDùng thay
Bảng chỉ đọc, không sắp xếp, không chọn, không phân trangTable
Danh sách thẻ không có quan hệ cộtCard

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ầnGhi chú
1Thanh 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ỗ đó.
2Nút cộtGhost, chỉ icon, mở Popover bật tắt cột. Cột enableHiding: false không tắt được.
3Header dínhNằm trong vùng cuộn của Table. Nút sắp xếp phủ kín ô và mang aria-sort.
4Tay nắm cộtKéo để xem trước, thả thì ghi chiều rộng. Mũi tên trái và phải bước 16px.
5Cột thao tácChỉ khi có rowActions. Dính bên phải. DataTableRowMenu là nút ⋯.
6Chân trangSelect 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.

SẴN SÀNG
Bảng sẵn sàng
Nguyễn Thị LanCần chú ý
Trần Văn MinhHoạt động
2 kết quả
Hàng / trang

Chọn hàng dùng nền selected và đếm id. Lựa chọn giữ theo id khi đổi trang.

RỖNG
Bảng rỗng
Không có dữ liệu phù hợp.
0 kết quả
Hàng / trang
LỖI
Bảng lỗi
Nguyễn Thị LanCần chú ý
Trần Văn MinhHoạt động
2 kết quả
Hàng / trang

Alert và nút thử lại. Hàng đã có được giữ. Lỗi bỏ qua khoảng chờ skeleton.

ĐANG TẢI LẦN ĐẦU
Bảng đang tải
0 kết quả
Hàng / trang

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.

ĐANG CẬP NHẬT
Bảng đang cập nhật
Nguyễn Thị LanCần chú ý
Trần Văn MinhHoạt động
2 kết quả
Hàng / trang

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

Sắp xếp là button phủ kín ô tiêu đề. Cột đang sắp có aria-sort.
Chọn hàng là checkbox có nhãn, kể cả trạng thái indeterminate ở header.
Đổi rộng cột: mũi tên trái và phải trên tay nắm, bước 16px.
Vùng cuộn là region, vào được bằng Tab.
Nút cột và nút ⋯ chỉ có icon nên phải có tên trợ năng.
Primitive Table không thêm các phím này.

API & triển khai

PropMặc địnhQuy ước
databắt buộcHàng của trang hiện tại, hoặc toàn bộ khi mode local
columnsbắt buộcĐịnh nghĩa cột TanStack. Id cột ổn định
getRowIdbắt buộcId hàng ổn định, khoá của lựa chọn
labelbắt buộcTên trợ năng của vùng bảng
modelocalserver cần pagination, sorting và rowCount hoặc pageCount
loadingfalseChỉ 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
emptyMessageKhông có dữ liệu phù hợp.Hiện trong bảng khi không có hàng
selectablefalseCheckbox theo trang. Lựa chọn giữ giữa các trang
selectionScopedefaultĐổ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
chromecardplain 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
maxHeightmin(65vh, 42rem)Chiều cao vùng cuộn
columnSettingstruefalse ẩ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.