表格

New

虚拟滚动数据表格,万行以上依然流畅,支持表头排序、行选择、列宽调整与列重排,并带粘性表头。动效克制,对「减少动效」偏好友好。

数据表格

index.tsx

支持万行级虚拟滚动,表头可排序,支持行选择、列宽调整与列重排。

10,000 rows
Email
Status

安装

$ bunx --bun shadcn add @uilab/table

API 参考

data
T[]
columns
TableColumn<T>[]
getRowId?
((row: T, index: number) => string)

Stable id per row, required for correct selection across sorts. Defaults to row index.

selectable?
boolean

Render a leading checkbox column with select-all in the header.

false
selectedRowIds?
string[]
defaultSelectedRowIds?
string[]
onSelectionChange?
((ids: string[]) => void)
sort?
SortState | null
defaultSort?
SortState | null
null
onSortChange?
((sort: SortState | null) => void)
resizable?
boolean

Allow dragging the right edge of a header to resize that column.

false
minColumnWidth?
number

Minimum column width in px when resizing.

64
onColumnResize?
((key: string, width: number) => void)
reorderable?
boolean

Allow dragging a header grip to reorder columns.

false
onColumnOrderChange?
((keys: string[]) => void)
onCellEdit?
((rowId: string, columnKey: string, value: string) => void)

Called when an `editable` cell changes.

onColumnRename?
((columnKey: string, value: string) => void)

When set, non-sortable headers become editable inputs for the column name.

onInsertRow?
((index: number, position: InsertPosition) => void)

Enables the row menu (Insert before / after). Receives the target index.

onDeleteRow?
((rowId: string, index: number) => void)

Enables Delete in the row menu.

onInsertColumn?
((index: number, position: InsertPosition) => void)

Enables the column menu (Insert before / after). Receives the target column index.

onDeleteColumn?
((columnKey: string, index: number) => void)

Enables Delete in the column menu.

rowHeight?
number

Fixed row height in px — required for virtualization.

48
height?
number

Scroll viewport height in px.

440
overscan?
number

Rows rendered above/below the viewport.

10
onEndReached?
(() => void)

Fires when the viewport scrolls near the bottom — load the next page.

loading?
boolean

Currently fetching — shows skeleton rows and pauses `onEndReached`.

false
skeletonRows?
number

How many skeleton rows to show while loading more (default 3).

3
emptyState?
ReactNode
No data
className?
string

可编辑表格

index.tsx

行内编辑单元格,通过边框手柄插入或删除行列;表格会根据更新后的数据与列定义重新渲染。

Click a cell to edit. Use the column and row handles to insert or delete.

安装

$ bunx --bun shadcn add @uilab/table-editable

API 参考

data
T[]
columns
TableColumn<T>[]
getRowId?
((row: T, index: number) => string)

Stable id per row, required for correct selection across sorts. Defaults to row index.

selectable?
boolean

Render a leading checkbox column with select-all in the header.

false
selectedRowIds?
string[]
defaultSelectedRowIds?
string[]
onSelectionChange?
((ids: string[]) => void)
sort?
SortState | null
defaultSort?
SortState | null
null
onSortChange?
((sort: SortState | null) => void)
resizable?
boolean

Allow dragging the right edge of a header to resize that column.

false
minColumnWidth?
number

Minimum column width in px when resizing.

64
onColumnResize?
((key: string, width: number) => void)
reorderable?
boolean

Allow dragging a header grip to reorder columns.

false
onColumnOrderChange?
((keys: string[]) => void)
onCellEdit?
((rowId: string, columnKey: string, value: string) => void)

Called when an `editable` cell changes.

onColumnRename?
((columnKey: string, value: string) => void)

When set, non-sortable headers become editable inputs for the column name.

onInsertRow?
((index: number, position: InsertPosition) => void)

Enables the row menu (Insert before / after). Receives the target index.

onDeleteRow?
((rowId: string, index: number) => void)

Enables Delete in the row menu.

onInsertColumn?
((index: number, position: InsertPosition) => void)

Enables the column menu (Insert before / after). Receives the target column index.

onDeleteColumn?
((columnKey: string, index: number) => void)

Enables Delete in the column menu.

rowHeight?
number

Fixed row height in px — required for virtualization.

48
height?
number

Scroll viewport height in px.

440
overscan?
number

Rows rendered above/below the viewport.

10
onEndReached?
(() => void)

Fires when the viewport scrolls near the bottom — load the next page.

loading?
boolean

Currently fetching — shows skeleton rows and pauses `onEndReached`.

false
skeletonRows?
number

How many skeleton rows to show while loading more (default 3).

3
emptyState?
ReactNode
No data
className?
string

异步加载表格

index.tsx

按需分页加载——首次加载展示骨架行,随后虚拟列表接近底部时通过 onEndReached 触发无限滚动加载。

0 loadedLoading…
Name
Email
Role
Status
MRR

安装

$ bunx --bun shadcn add @uilab/table-async

API 参考

data
T[]
columns
TableColumn<T>[]
getRowId?
((row: T, index: number) => string)

Stable id per row, required for correct selection across sorts. Defaults to row index.

selectable?
boolean

Render a leading checkbox column with select-all in the header.

false
selectedRowIds?
string[]
defaultSelectedRowIds?
string[]
onSelectionChange?
((ids: string[]) => void)
sort?
SortState | null
defaultSort?
SortState | null
null
onSortChange?
((sort: SortState | null) => void)
resizable?
boolean

Allow dragging the right edge of a header to resize that column.

false
minColumnWidth?
number

Minimum column width in px when resizing.

64
onColumnResize?
((key: string, width: number) => void)
reorderable?
boolean

Allow dragging a header grip to reorder columns.

false
onColumnOrderChange?
((keys: string[]) => void)
onCellEdit?
((rowId: string, columnKey: string, value: string) => void)

Called when an `editable` cell changes.

onColumnRename?
((columnKey: string, value: string) => void)

When set, non-sortable headers become editable inputs for the column name.

onInsertRow?
((index: number, position: InsertPosition) => void)

Enables the row menu (Insert before / after). Receives the target index.

onDeleteRow?
((rowId: string, index: number) => void)

Enables Delete in the row menu.

onInsertColumn?
((index: number, position: InsertPosition) => void)

Enables the column menu (Insert before / after). Receives the target column index.

onDeleteColumn?
((columnKey: string, index: number) => void)

Enables Delete in the column menu.

rowHeight?
number

Fixed row height in px — required for virtualization.

48
height?
number

Scroll viewport height in px.

440
overscan?
number

Rows rendered above/below the viewport.

10
onEndReached?
(() => void)

Fires when the viewport scrolls near the bottom — load the next page.

loading?
boolean

Currently fetching — shows skeleton rows and pauses `onEndReached`.

false
skeletonRows?
number

How many skeleton rows to show while loading more (default 3).

3
emptyState?
ReactNode
No data
className?
string

Keep in mind

Some components on this site are inspired by or recreated from existing work across the web. I'm not here to take credit; just to learn, experiment, and sometimes push things a bit further. If something looks familiar and I forgot to mention you, reach out and I'll fix that right away.