关于 niko-table-best-practices
niko-table-best-practices 是帮助开发者使用 Niko Table 构建和配置数据表的技能。内容涵盖组件组合、筛选、拖放、服务端模式、URL 状态和可编辑网格,并根据具体任务提供指导。
主要功能
- 01推荐数据表组件结构
- 02配置搜索和高级筛选
- 03设置行列拖放
- 04指导服务端数据表状态
- 05将表格状态同步到 URL
- 06构建可编辑 Data Grid
适用场景
- 01创建带分页和筛选的数据表
- 02为数据表添加分组或拖放
- 03将表格查询连接到服务端
- 04构建类似电子表格的可编辑网格
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ semkoo/ niko-table-registry --skill niko-table-best-practices安装后在 Claude Code 中输入/niko-table-best-practices确认已加载。
详细介绍
Niko Table 集成指南
使用 Niko Table 构建和配置数据表格的技能:结构、筛选器(搜索、分面、高级筛选)、列菜单、拖放、服务端模式和可编辑数据网格。
概览:
- 新建表格:DataTableRoot → ToolbarSection(可选)→ DataTable → Header + Body(Skeleton、EmptyBody)→ Pagination。仅使用直接文件导入(不要使用 barrel exports)。如果由你管理 TanStack 实例,请为所有者安装
@niko-table/data-table;按需使用的控件依赖@niko-table/data-table-core(上下文 + 结构,不含 Root)。 - 添加筛选器:工具栏 = DataTableSearchFilter、DataTableFacetedFilter、DataTableFilterMenu。列标题 = DataTableColumnFacetedFilterMenu、DataTableColumnSliderFilterMenu、DataTableColumnDateFilterMenu。设置列
meta(variant、options 等),并设置enableColumnFilter: true。 - 行/列拖放:行拖放需要
getRowId,并将 DataTableRowDndProvider 放在 DataTable 外部;不要将行拖放与排序/筛选结合使用。列拖放可安全地与所有功能结合使用。 - 分组:在
DataTableColumnActions中挂载DataTableColumnGroupOptions(或设置config.enableGrouping)。使用aggregationFn/aggregatedCell汇总数据,并使用getGroupingValue创建分组桶(例如按月)。不要与行拖放或树形getSubRows结合使用——树形表 = 嵌套数据;分组 = 按列分桶的平面行。请参阅 niko-table.com 上的 Grouping Table / Tree Table。 - 服务端:设置
config.manualPagination/manualSorting/manualFiltering+config.pageCount,将totalCount传给 DataTablePagination,并在DataTable上设置maxHeight,以便更改每页行数时可以滚动。围绕可序列化的传输契约构建结构——使用一个函数fetch(query: { page, pageSize, sorting, search, columnFilters })→{ data, total, facets }——即可接入任何后端(SQL、Drizzle、Prisma、Supabase、REST);请参阅 niko-table.com 上的 Server-Side Table 示例和 Drizzle ORM 指南。 - URL 状态(nuqs):使用
NuqsAdapter包装应用;使用带解析器的useQueryStates管理分页、排序、筛选器和搜索;将 URL 派生的状态传入DataTableRoot,并将onPaginationChange/onSortingChange/onColumnFiltersChange/onGlobalFilterChange连接到setUrlParams。 - 大型列表:对于 10k+ 行,请使用
DataTableVirtualizedBody(来自 core/structure)替代DataTableBody;子项相同(Skeleton、EmptyBody)。请参阅 Virtualization Table 示例。 - 侧边栏:使用
DataTableAside(及其触发器)在表格旁显示详情面板。请参阅 Aside Table 示例。 - 数据网格:使用
useDataGrid+<DataGrid grid={grid}>,在DataTableRoot内包裹 DataTable。剪贴板/填充/移动功能需选择启用子项。通过<DataGridCell>+Grid*Cell设置单元格编辑器。安装@niko-table/data-table-grid(持久化还需安装data-table-grid-changes)。在网格内挂载<DataTableColumnResize />,使列弹性填满宽度,并为<DataGrid>传入className="space-y-2 outline-none"以设置间距。对于由服务端提供数据的网格,不要分页——应在滚动时流式加载数据块(请参阅下文的服务端模式)。请参阅 niko-table.com 上的 Basic Grid / Data Grid 文档。
使用此技能时,你的任务是判断用户当前的需求——新建表格、添加筛选器/拖放/分组、修复导入、接入服务端、URL 状态(nuqs)、行展开、树形表格、行选择或可编辑数据网格——并提供合适的结构、导入方式和模式。如果用户描述含糊(“我想要一个表格”),请推荐最简模板,并引导其查看 niko-table.com 上的示例。如果用户已有表格,想添加分面筛选器或高级筛选菜单,请直接跳转到 Filtering 部分。如果用户想要电子表格编辑功能,请转到 Data Grid。灵活应对:有些用户想要可直接复制粘贴的代码片段;有些用户则想了解双层(DataTable* 与 Table*)模式。
完整文档和示例:**https://niko-table.com**。组件注册表:在 components.json 的 registries["@niko-table"] 中使用 https://niko-table.com/r/{name}.json。
快速参考
- 文档和示例:https://niko-table.com(安装、示例、API 概览)
- 注册表 URL:
https://niko-table.com/r/{name}.json— 添加到components.json的registries["@niko-table"]下
与用户沟通
用户可能刚接触 Niko Table 或 shadcn/TanStack 技术栈。如有疑问,请简要说明直接导入为何重要(可进行树摇优化,且无需使用 barrel 文件),以及行拖放(DnD)为何需要 getRowId。请说明,大多数 DataTableRoot 配置会根据他们使用的组件自动检测,因此只有在需要覆盖配置或使用手动/服务端模式时,才需要传入 config。如需深入参考(所有附加组件、完整 API),请指向 niko-table.com。
**不适用场景:**如果项目明显使用其他表格库(例如 AG Grid、MUI Data Grid,或未使用此注册表的 TanStack Table),不要强行推荐 Niko Table,而应建议适合其技术栈的模式。
表格结构
所有表格 UI 都必须位于 DataTableRoot 内。推荐的组合方式:
DataTableRoot (required)
→ DataTableToolbarSection (optional: search, filters, view menu)
→ DataTable
→ DataTableHeader
→ DataTableBody
→ DataTableSkeleton (when loading)
→ DataTableEmptyBody (when no data)
→ DataTablePagination (optional)
**可选:**将表格(或 DataTableRoot)包裹在来自 @/components/niko-table/core/data-table-error-boundary 的 DataTableErrorBoundary 中,这样渲染错误会显示回退 UI,而不会导致页面崩溃。
导入 — 不使用 Barrel 导出
仅使用直接文件路径。不要使用 core、components 或 filters 的 index.ts 重新导出。
| 用途 | 导入路径 |
|---|---|
| 根组件和表格 | @/components/niko-table/core/data-table-root、@/components/niko-table/core/data-table |
| 结构 | @/components/niko-table/core/data-table-structure(Header、Body、Skeleton、EmptyBody) |
| 工具栏 / 筛选器 | @/components/niko-table/components/data-table-toolbar-section、data-table-search-filter、data-table-pagination 等。 |
| 类型 | @/components/niko-table/types(例如 DataTableColumnDef) |
示例:
import { DataTableRoot } from "@/components/niko-table/core/data-table-root"
import { DataTable } from "@/components/niko-table/core/data-table"
import {
DataTableHeader,
DataTableBody,
DataTableSkeleton,
DataTableEmptyBody,
} from "@/components/niko-table/core/data-table-structure"
import { DataTableToolbarSection } from "@/components/niko-table/components/data-table-toolbar-section"
import { DataTableSearchFilter } from "@/components/niko-table/components/data-table-search-filter"
import { DataTablePagination } from "@/components/niko-table/components/data-table-pagination"
import type { DataTableColumnDef } from "@/components/niko-table/types"
双层组件模式
- 组件(
DataTable*):感知上下文;内部使用useDataTable()。从components/导入。常规使用时(无需table属性)优先选择这些组件。 - 筛选器(
Table*):接受table属性;从filters/导入。构建自定义组件或自行管理表格实例时使用。
基于上下文使用时,从直接路径(例如 data-table-pagination)导入 DataTable* 组件;需要底层 API 时,使用 filters 中的 Table*。
列定义
- 类型:来自
@/components/niko-table/types的DataTableColumnDef<TData>[]。 - 使用
accessorKey和header。对于可排序/可筛选的列,请使用DataTableColumnHeader、DataTableColumnTitle和DataTableColumnSortMenu(并按需使用列筛选菜单)。 - 筛选配置使用 meta:
label、placeholder、variant(text、select、multi_select、range、date、date_range、number、boolean)、options(静态{ label, value }[])、autoOptions(根据数据生成)、unit(例如范围筛选的"$")、showCounts、dynamicCounts、mergeStrategy(针对选项的"preserve"|"augment"|"replace")。使用列筛选器时,请设置enableColumnFilter: true。
筛选
工具栏筛选器(位于 DataTableToolbarSection 内)
- 全局搜索:
DataTableSearchFilter— 单个搜索输入框;无需列 meta。 - 高级筛选(基于规则):
DataTableFilterMenu— 命令面板样式;可添加多个 AND/OR 筛选规则。列的meta.variant(例如text、select、range、date)决定筛选类型。安装@niko-table/data-table-filter-menu,多选时还可选装 Shadcn 的checkbox。 - 分面筛选(内联):
DataTableFacetedFilter— 每列一个筛选器;显示带计数的选项。使用accessorKey关联到某一列;选项来自列的meta.options或meta.autoOptions。多选时使用multiple。limitToFilteredRows会将选项限制为当前结果集。 - 其他工具栏筛选器:使用
DataTableSliderFilter、DataTableDateFilter在工具栏中进行范围或日期筛选;使用DataTableClearFilter清除所有筛选器。
列级筛选菜单(位于表头中)
在列的 header 内,紧挨着 DataTableColumnTitle 和 DataTableColumnSortMenu 渲染:
- 分面筛选:
DataTableColumnFacetedFilterMenu— 带计数的单选/多选。列需要设置meta.options或meta.autoOptions;可选设置meta.showCounts、meta.dynamicCounts、meta.mergeStrategy。必要时,在DataTableColumnSortMenu上使用FILTER_VARIANTS.TEXT(或.NUMBER、.DATE)。 - 滑块(范围):
DataTableColumnSliderFilterMenu— 数值范围;列的meta.variant: "range",可选设置meta.unit。 - 日期:
DataTableColumnDateFilterMenu— 日期或日期范围;列的meta.variant: "date"或"date_range"。
带分面筛选和排序的列示例:
import { DataTableColumnHeader, DataTableColumnTitle } from "@/components/niko-table/components/data-table-column-header"
import { DataTableColumnSortMenu } from "@/components/niko-table/components/data-table-column-sort"
import { DataTableColumnFacetedFilterMenu } from "@/components/niko-table/components/data-table-column-faceted-filter"
import { FILTER_VARIANTS } from "@/components/niko-table/lib/constants"
{
accessorKey: "category",
header: () => (
<DataTableColumnHeader>
<DataTableColumnTitle />
<DataTableColumnSortMenu variant={FILTER_VARIANTS.TEXT} />
<DataTableColumnFacetedFilterMenu multiple limitToFilteredRows={false} />
</DataTableColumnHeader>
),
meta: {
label: "Category",
options: categoryOptions,
mergeStrategy: "augment",
dynamicCounts: true,
showCounts: true,
},
enableColumnFilter: true,
}
带搜索、分面筛选、高级筛选和清除按钮的工具栏示例:
<DataTableToolbarSection>
<DataTableSearchFilter placeholder="Search..." />
<DataTableFacetedFilter accessorKey="category" title="Category" options={categoryOptions} multiple />
<DataTableFacetedFilter accessorKey="brand" limitToFilteredRows />
<DataTableFilterMenu autoOptions dynamicCounts showCounts mergeStrategy="augment" />
<DataTableViewMenu />
<DataTableClearFilter />
</DataTableToolbarSection>
附加组件:data-table-search-filter、data-table-filter-menu、data-table-faceted-filter、data-table-clear-filter、data-table-slider-filter、data-table-date-filter、data-table-column-faceted-filter、data-table-column-slider-filter、data-table-column-date-filter。完整列表请访问 niko-table.com。
DataTableRoot 配置和状态
大多数配置会根据你渲染的组件自动检测:例如,DataTablePagination 会启用分页;DataTableSearchFilter / DataTableFilterMenu / DataTableFacetedFilter / 列筛选菜单会启用筛选;DataTableColumnHeader / DataTableColumnSortMenu 会启用排序;DataTableSelectionBar 会启用行选择。只有在需要覆盖默认值或启用子组件未声明的功能(例如服务端或手动模式)时,才需要传入 config。
- config(按需覆盖):
manualPagination、manualSorting、manualFiltering、pageCount、initialPageSize、initialPageIndex、autoResetPageIndex、autoResetExpanded,或用于关闭某项功能。完整列表:enablePagination、enableSorting、enableFilters、enableRowSelection、enableExpanding等。 - state:可选的受控
state,以及onPaginationChange、onSortingChange、onColumnFiltersChange、onColumnVisibilityChange、onRowSelectionChange、onExpandedChange、onRowSelection。 - getRowId:可选的
(row, index) => string。使用行拖放(DnD)、行选择或展开功能时,请使用稳定的唯一 ID(例如(row) => row.id)——基于索引的默认 ID 会在重新排序后失效。 - 加载状态:在
DataTableRoot上设置isLoading;在DataTableBody内渲染DataTableSkeleton和DataTableEmptyBody。
URL 状态(nuqs)
将表格状态(分页、排序、筛选、搜索)与 URL 同步,以便分享和收藏视图。使用 nuqs:安装 nuqs,并在应用根节点使用对应框架的 NuqsAdapter 包裹应用(nuqs/adapters/next/app、nuqs/adapters/next/pages 或 nuqs/adapters/react)。有关设置方法,请参阅 nuqs adapters docs。
- 解析器: 使用
parseAsInteger.withDefault(0)为pageIndex/pageSize定义解析器,使用parseAsJson处理sort/filters,使用parseAsString处理search。匹配 TanStack Table 的状态结构,使 URL 参数与state一一对应。 - 接线:
useQueryStates(parsers, { history: "replace" })→[urlParams, setUrlParams]。从urlParams派生pagination、sorting、columnFilters、globalFilter(例如通过useMemo)。将它们作为state={{ pagination, sorting, columnFilters, globalFilter }}传给DataTableRoot。在onPaginationChange、onSortingChange、onColumnFiltersChange、onGlobalFilterChange中,调用setUrlParams并传入更新后的部分状态,以保持 URL 同步。 - DataTableFilterMenu: 使用 nuqs 搭配筛选菜单时,URL 中的筛选条件通常以扩展筛选对象的形式存储;在处理函数中,使用
serializeFiltersForUrl/normalizeFiltersFromUrl(从filters/table-filter-menu导出)在 TanStackColumnFiltersState与该结构之间转换(它们会移除/重新生成filterId,以缩短 URL 并保持输入焦点稳定)。请参阅 niko-table.com 上的 Advanced Nuqs Table 和 Server-Side Nuqs Table 示例。
安装(适用于未使用 Niko Table 的项目)
- 前置条件:React 项目、Shadcn UI、TailwindCSS、TypeScript。
- 客户端组件:表格组件使用 React 状态和 Hook;在任何渲染
DataTableRoot或 Niko Table 组件的文件顶部添加"use client"(Next.js App Router 等场景中必须添加)。 - 注册表:在
components.json中添加:"registries": { "@niko-table": "https://niko-table.com/r/{name}.json" } - 核心组件:
shadcn@latest add @niko-table/data-table(会拉取data-table-core+data-table-ui+ Root/外观组件;安装/更新components/ui/table.tsx,其中包含TableComponent和支持键盘聚焦的滚动容器)。如果只需要控件/自有 TanStack 实例:安装控件项即可——它们会解析data-table-core,而不包含 Root 或table.tsx。只有在需要我们的表格原语时才添加@niko-table/data-table-ui。 - 附加组件(示例):
@niko-table/data-table-pagination、@niko-table/data-table-search-filter、@niko-table/data-table-view-menu、@niko-table/data-table-sort-menu、@niko-table/data-table-filter-menu,以及按需添加列级筛选/排序组件。请使用 niko-table.com 注册表中的对应名称。 - 服务端:对于
manualPagination/manualSorting/manualFiltering,设置config.pageCount(例如Math.ceil(totalCount / pageSize));使用服务端驱动的数据时,将totalCount传给DataTablePagination。
拖放
- 行拖放: 不要与排序或筛选同时使用(数据顺序会冲突)。需要
getRowId={(row) => row.id}(或类似的稳定 ID)——重排后,基于索引的 ID 会失效。在<DataTable>外部使用DataTableRowDndProvider包裹(拖放上下文使用的 div 不能放在<table>内)。内部使用DataTableDndBody和DataTableRowDragHandle。添加拖动手柄列:cell: ({ row }) => <DataTableRowDragHandle rowId={row.id} />。 - 列拖放: 可以安全地与其他功能同时使用。使用
DataTableColumnDndProvider、DataTableDraggableHeader、DataTableDragAlongCell以及对应的核心结构组件(需要时包括虚拟化变体)。
样式
使用语义化颜色令牌(例如 bg-success、text-destructive),不要使用硬编码的 Tailwind 颜色。
应避免的陷阱
- 不要使用 barrel import:不要从
@/components/niko-table、.../core或.../components导入;必须使用包含文件完整路径的导入(例如.../core/data-table-root)。 - 行拖放时未指定 getRowId:行拖放需要稳定的行 ID;请传入
getRowId={(row) => row.id}(或你的 ID 字段)。省略该项或使用索引会导致重新排序后行为错误。 - 同时启用行拖放和排序/筛选:不要同时启用行重新排序和排序/筛选;数据顺序会变得模糊。
- 将 DataTableRowDndProvider 放在 <table> 内部:Provider 必须从外部包裹整个
DataTable;其标记不能放入<table>内。
最简表格模板
"use client"
import { DataTableRoot } from "@/components/niko-table/core/data-table-root"
import { DataTable } from "@/components/niko-table/core/data-table"
import {
DataTableHeader,
DataTableBody,
DataTableSkeleton,
DataTableEmptyBody,
} from "@/components/niko-table/core/data-table-structure"
import { DataTableToolbarSection } from "@/components/niko-table/components/data-table-toolbar-section"
import { DataTableSearchFilter } from "@/components/niko-table/components/data-table-search-filter"
import { DataTablePagination } from "@/components/niko-table/components/data-table-pagination"
import type { DataTableColumnDef } from "@/components/niko-table/types"
type User = { id: string; name: string; email: string }
const columns: DataTableColumnDef<User>[] = [
{ accessorKey: "name", header: "Name" },
{ accessorKey: "email", header: "Email" },
]
export function UsersTable({ data, isLoading }: { data: User[]; isLoading?: boolean }) {
return (
<DataTableRoot data={data} columns={columns} isLoading={isLoading}>
<DataTableToolbarSection>
<DataTableSearchFilter placeholder="Search..." />
</DataTableToolbarSection>
<DataTable>
<DataTableHeader />
<DataTableBody>
<DataTableSkeleton />
<DataTableEmptyBody />
</DataTableBody>
</DataTable>
<DataTablePagination />
</DataTableRoot>
)
}
数据网格
基于同一 DataTableRoot/虚拟化主体构建的可编辑电子表格样式网格。不要另行设计独立的组件 API。
DataTableRoot data={grid.rows} getRowId={(r) => r.id}
→ DataGrid grid={grid}
→ opt-in: DataGridClipboard, DataGridFillHandle, DataGridMove, …
→ DataTable → VirtualizedHeader + VirtualizedBody (fixed height)
- 引擎:
useDataGrid({ columnIds, createEmptyRow, initialRows? })— 非受控行,按{ rowId, columnId }管理焦点/选中状态,支持撤销/重做。 - **单元格:**使用
<DataGridCell row={…} columnId={…}>包裹编辑器。可使用GridTextCell、GridNumberCell、GridCheckboxCell、GridDateCell、GridSelectCell/GridComboboxCell。有效性由你的resolve→CellState决定。 - **可选功能:**仅作为
<DataGrid>的子项挂载 — 未挂载的功能会被 tree-shaken。 - **持久化:**单独安装
@niko-table/data-table-grid-changes→useGridChanges(grid, { initialRows })。 - **服务端网格:**不使用分页 — 通过
DataTableVirtualizedBody的onNearEnd+prefetchThreshold在滚动时流式加载行。使用grid.updateRows(() => rows, { history: false })+changes.reset(rows)加载每个数据块,并在changes.dirtyRowIds周围合并数据,以保留未保存的编辑。通过changes.getChangeSet()→ POST{ created, updated, deleted }→changes.reconcile({ succeededIds, failedIds })保存;失败的行会保持脏状态(使用failedRowIds高亮)。将useDataGrid的maxRows(默认值为 200)调高至预期加载行数以上。请参阅 Server-Side Grid 示例。 - **文档:**https://niko-table.com/data-grid/introduction/ · https://niko-table.com/examples/basic-grid/
了解更多
- **在线:**https://niko-table.com — 安装、示例、组件概览、API。表格示例:Simple / Basic / Faceted / Advanced / Nuqs / Server-Side / Server-Side Nuqs / Infinite Scroll / Row DnD / Column DnD / Virtualization / Aside;Drizzle ORM 指南(包含展示生成 SQL 的实时模拟演示)实现了服务端线协议。数据网格示例:Basic Grid、Cell Types、Validation、Dynamic Columns、Persistence、Server Side。增强稳定性:DataTableErrorBoundary(core/data-table-error-boundary)。
- **技能(AI):**https://niko-table.com/getting-started/skills/ — 了解如何安装和使用此技能。
- **文档指南:**https://niko-table.com/contributing/documentation-guidelines/
- 仓库内(在 niko-table-registry 中工作时):
src/content/docs/— 例如getting-started/installation.mdx、niko-table/overview/、data-grid/overview/、examples/*-table.mdx、examples/*-grid.mdx。