mcpField
N
niko-table-best-practices

niko-table-best-practices

github.com/semkoo開発7280 回インストール3 日前に更新
リポジトリ

niko-table-best-practices について

niko-table-best-practicesは、Niko Tableでテーブルを構築・設定する開発者向けのスキルです。コンポーネント構成、フィルター、ドラッグ&ドロップ、サーバー側処理、URL状態、編集可能なグリッドを扱い、作業内容に応じた指針を示します。

主な機能

  1. 01テーブルのコンポーネント構成を提案
  2. 02検索と高度なフィルターを設定
  3. 03行と列のドラッグ&ドロップを設定
  4. 04サーバー側テーブルの状態を案内
  5. 05テーブル状態をURLと同期
  6. 06編集可能なData Gridを構築

活用シーン

  1. 01ページネーションとフィルター付きテーブルを作成
  2. 02テーブルにグループ化やドラッグ&ドロップを追加
  3. 03テーブルのクエリをサーバーバックエンドに接続
  4. 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 でデータテーブルを構築、設定するためのスキルです。構造、フィルター(検索、ファセット、詳細設定)、列メニュー、ドラッグ&ドロップ、サーバーサイドのパターン、編集可能な Data Grid を扱います。

概要:

  • 新しいテーブル:DataTableRoot → ToolbarSection(任意)→ DataTable → Header + Body(Skeleton、EmptyBody)→ Pagination。直接ファイルからのみインポートしてください(バレルエクスポートは使用しません)。所有者向けには @niko-table/data-table をインストールします。TanStack インスタンスを自分で所有する場合、個別に選択して使うコントロールは @niko-table/data-table-core(コンテキスト + 構造、Root なし)に依存します。
  • フィルターの追加:ツールバーには DataTableSearchFilter、DataTableFacetedFilter、DataTableFilterMenu を使用します。列ヘッダーには DataTableColumnFacetedFilterMenu、DataTableColumnSliderFilterMenu、DataTableColumnDateFilterMenu を使用します。列の meta(variant、options など)を設定し、enableColumnFilter: true にしてください。
  • 行/列のドラッグ&ドロップ:行のドラッグ&ドロップには getRowId と、DataTable の外側にある DataTableRowDndProvider が必要です。行のドラッグ&ドロップは並べ替えやフィルタリングと組み合わせないでください。列のドラッグ&ドロップは、ほかの機能と組み合わせても問題ありません。
  • グループ化:DataTableColumnActions(または config.enableGrouping)に DataTableColumnGroupOptions をマウントします。集計には aggregationFn/aggregatedCell を、バケット分け(例:月)には getGroupingValue を使用します。行のドラッグ&ドロップや、ツリーの getSubRows と組み合わせないでください。ツリーはネストされたデータを扱い、グループ化はフラットな行を列ごとにバケット分けします。niko-table.com の Grouping Table/Tree Table を参照してください。
  • サーバーサイド:config.manualPagination/manualSorting/manualFiltering と config.pageCount を設定し、DataTablePagination に totalCount を渡します。また、ページサイズの変更時にスクロールできるよう、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 に接続します。
  • 大規模なリスト:1 万行以上では、DataTableBody の代わりに(core/structure から)DataTableVirtualizedBody を使用します。子要素(Skeleton、EmptyBody)は同じです。Virtualization Table の例を参照してください。
  • サイドバー:テーブルの横に詳細パネルを表示するには、DataTableAside(およびトリガー)を使用します。Aside Table の例を参照してください。
  • Data Grid: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)、行の展開、ツリーテーブル、行選択、編集可能な Data Grid)を見極め、適切な構造、インポート、パターンを提示してください。ユーザーの要望が曖昧な場合(「テーブルがほしい」など)は、最小限のテンプレートを提案し、niko-table.com の例を案内してください。すでにテーブルがあり、ファセットフィルターや詳細フィルターメニューを使いたい場合は、Filtering セクションを参照してください。スプレッドシートのような編集を希望する場合は、Data Grid を参照してください。柔軟に対応してください。コピーして貼り付けられるスニペットを求めるユーザーもいれば、2 層構造(DataTable* 対 Table*)のパターンを理解したいユーザーもいます。

完全なドキュメントと例:**https://niko-table.com**。レジストリ:`components.json` の registries["@niko-table"] にある https://niko-table.com/r/{name}.json。

クイックリファレンス

ユーザーとのコミュニケーション

ユーザーは Niko Table や shadcn/TanStack のスタックに不慣れな場合があります。迷ったときは、直接インポートする理由(ツリーシェイキング、バレルファイルを使わないこと)と、行の 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 を表示できます。

インポート — バレルエクスポートなし

直接のファイルパスのみを使用してください。コア、コンポーネント、フィルターでは 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"

2 層コンポーネントパターン

  • コンポーネント(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 を参照してください。

  • パーサー: pageIndex/pageSize には parseAsInteger.withDefault(0)、sort/filters には parseAsJson、search には parseAsString を使ってパーサーを定義します。URL パラメーターが state に 1 対 1 で対応するよう、TanStack Table の状態の形に合わせてください。
  • 接続: useQueryStates(parsers, { history: "replace" }) → [urlParams, setUrlParams] を使います。urlParams から pagination、sorting、columnFilters、globalFilter を導出します(例:useMemo を使用)。state={{ pagination, sorting, columnFilters, globalFilter }} として DataTableRoot に渡します。URL と同期した状態を保つため、onPaginationChange、onSortingChange、onColumnFiltersChange、onGlobalFilterChange では、更新された部分を setUrlParams に渡します。
  • DataTableFilterMenu: nuqs でフィルターメニューを使う場合、URL 内のフィルターは拡張されたフィルターオブジェクトとして保存されることがよくあります。ハンドラー内で serializeFiltersForUrl/normalizeFiltersFromUrl(filters/table-filter-menu からエクスポート。URL を短く保ち、入力フォーカスを安定させるために filterId を削除/再生成します)を使い、TanStack の ColumnFiltersState とその形式の間で変換してください。niko-table.com の Advanced Nuqs Table および Server-Side Nuqs Table の例を参照してください。

インストール(Niko Table を使わないプロジェクト向け)

  1. 前提条件:React プロジェクト、Shadcn UI、TailwindCSS、TypeScript。
  2. クライアントコンポーネント:テーブルコンポーネントは React の状態とフックを使用します。DataTableRoot または Niko Table コンポーネントをレンダリングするファイルの先頭に "use client" を追加してください(Next.js App Router などで必須です)。
  3. レジストリ:components.json に以下を追加します。
    "registries": {
      "@niko-table": "https://niko-table.com/r/{name}.json"
    }
    
  4. コア:shadcn@latest add @niko-table/data-table(data-table-core、data-table-ui、Root/chrome を取得します。また、TableComponent とキーボードでフォーカス可能なスクロールコンテナーを備えた components/ui/table.tsx をインストール/更新します)。コントロールのみを使う場合や独自の TanStack インスタンスを使う場合は、コントロール項目をインストールしてください。これらは Root や table.tsx を使わずに data-table-core を解決します。テーブルのプリミティブが必要な場合にのみ、@niko-table/data-table-ui を追加してください。
  5. アドオン(例):@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 のレジストリにある名前と一致させてください。
  6. サーバーサイド:manualPagination/manualSorting/manualFiltering を使う場合は、config.pageCount(例:Math.ceil(totalCount / pageSize))を設定し、サーバー主導のデータを使う際は totalCount を DataTablePagination に渡してください。

ドラッグ&ドロップ

  • 行の DnD: 並べ替えやフィルタリングとは併用しないでください(データの順序が競合します)。getRowId={(row) => row.id}(または同等の安定した ID)の指定が必要です。インデックスベースの ID は並べ替え後に正しく機能しません。<DataTable> の外側を DataTableRowDndProvider でラップしてください(DnD コンテキストでは <table> 内に配置できない div を使用します)。内部では DataTableDndBody と DataTableRowDragHandle を使用してください。cell: ({ row }) => <DataTableRowDragHandle rowId={row.id} /> を指定したドラッグハンドル列を追加します。
  • 列の DnD: ほかの機能と安全に併用できます。DataTableColumnDndProvider、DataTableDraggableHeader、DataTableDragAlongCell と、対応するコア構造コンポーネント(必要に応じて仮想化対応のバリアントを含む)を使用してください。

スタイル設定

ハードコードされた Tailwind の色ではなく、セマンティックなカラー トークン(例:bg-success、text-destructive)を使用してください。

避けるべき落とし穴

  • バレルインポートを使用しない:ファイルの完全なパス(例:.../core/data-table-root)を指定せずに、@/components/niko-table、.../core、.../componentsからインポートしないでください。
  • getRowId を指定しない行の DnD:行のドラッグ&ドロップには安定した行 ID が必要です。getRowId={(row) => row.id}(または独自の ID フィールド)を渡してください。省略したり、インデックスを使用したりすると、並べ替え後に動作が不正になります。
  • ソート/フィルターと行の DnD の併用:行の並べ替えとソート/フィルターを同時に有効にしないでください。データの順序が曖昧になります。
  • <table> 内の DataTableRowDndProvider:プロバイダーは外側から 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>の子としてマウントした場合にのみ有効です。マウントしなければ、ツリーシェイキングの対象になります。
  • 永続化: 別途@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)を、予想される読み込み件数より大きくしてください。サーバーサイドグリッドの例を参照してください。
  • ドキュメント: 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。

コメント