Data table
実データのためのテーブルです。並べ替え、検索、行の選択、固定列、スティッキーヘッダー、ページネーションを備えています。
| Method | Country | |||||
|---|---|---|---|---|---|---|
| [email protected] | Card | United States | 2026-01-01 | $5.00 | ||
| [email protected] | PayPal | Japan | 2026-02-02 | $84.20 | ||
| [email protected] | Bank | Germany | 2026-03-03 | $163.40 | ||
| [email protected] | Apple Pay | Brazil | 2026-04-04 | $242.60 | ||
| [email protected] | Card | India | 2026-05-05 | $321.80 | ||
| [email protected] | PayPal | United States | 2026-06-06 | $401.00 | ||
| [email protected] | Bank | Japan | 2026-07-07 | $480.10 | ||
| [email protected] | Apple Pay | Germany | 2026-08-08 | $559.30 | ||
| [email protected] | Card | Brazil | 2026-09-09 | $638.50 | ||
| [email protected] | PayPal | India | 2026-01-10 | $717.70 |
pnpm dlx shadcn@latest add https://hextaui.com/r/data-table.jsonコンポーネント、HextaUIのテーマトークン、依存するHextaUIコンポーネントを追加します。
まだ追加していない場合は、グローバルCSSにテーマトークンを追加してください。
依存関係をインストールします。
pnpm add @base-ui/react @tabler/icons-react @tanstack/react-table class-variance-authority cn次のコードをコピーしてプロジェクトに貼り付けてください。
components/ui/data-table.tsx components/ui/table.tsx components/ui/button.tsx components/ui/checkbox.tsx components/ui/skeleton.tsx インポートパスは、お使いのプロジェクト構成に合わせて更新してください。
Data table は、並べ替え、フィルタリング、ページネーション、選択、列の表示切り替えがすでに組み込まれた TanStack Table v9 です。createDataTableColumns で列を一度定義し、useDataTable でテーブルを作成し、必要なパーツを組み合わせます。
sorting や行の選択など、自分で管理したい TanStack の state を、その変更ハンドラーとともに渡します。
DataTableColumnHeader、DataTableSelectAll、DataTableSelectRow は、列の header または cell として、列定義の中に入れます。
プレーンなテーブル
Data table の構成要素となるプレーンな <Table /> パーツ。静的なデータに対して、キャプションとフッターの合計とともに、単独で使えます。
読み込み中
loading を指定すると、スケルトン行が実際の行と同じ空間を埋めるため、データが届いたときに何も跳ねません。その間、テーブルには aria-busy が付きます。
Empty
emptyMessage は、データがない場合や、検索に一致するものがない場合に、本体を埋めます。
固定ヘッダー
containerClassName でコンテナに最大の高さを指定し、stickyHeader を設定します。ヘッダーは固定されたままで、行がその下にスクロールすると細い線が加わります。チェックボックス上で Shift キーを押しながらドラッグし、ボックスの端に近づくとスクロールします。
固定列
選択列と最初のデータ列は、デフォルトで固定されます。pinStart で独自に選べます。テーブルが横にスクロールすると、柔らかい影が端を示します。
右から左
すべてのラベルと件数は、labels と整形関数で置き換えられます。ページネーションの矢印と固定列は、方向に合わせて反転します。
- 並べ替え可能なヘッダーをクリックすると昇順、もう一度で降順、3 回目で解除になります。別のヘッダーを Shift キーを押しながらクリックすると、2 次ソートが追加されます。
- 行のチェックボックスを Shift キーを押しながらクリックすると、前回クリックした行との間のすべての行が選択されます。Shift キーを押しながらチェックボックス上をドラッグすると、範囲を一度に選択または解除できます。
- 検索は、選択列を除くすべての列に一致し、最初のページに戻ります。
- View メニューで列を非表示にしてもメニューは開いたままなので、複数の列をまとめて切り替えられます。
| キー | アクション |
|---|---|
| Tab | 検索、View メニュー、並べ替え可能なヘッダー、行のチェックボックス、ページネーションの間を移動します。 |
| EnterSpace | フォーカス中のヘッダーで並べ替えます。 |
| Space | フォーカス中のチェックボックスを切り替えます。 |
| Esc | テキストが入力されている場合、検索をクリアします。 |
- 並べ替え可能なヘッダーには
aria-sortが付き、polite なライブリージョンが、新しい並べ替えと、入力の少し後に結果の件数を通知します。 - ページインジケーターはライブリージョンなので、次へまたは前へを押した後、スクリーンリーダーが新しいページを読み上げます。
- チェックボックスにはデフォルトでラベルが付いています。
<DataTableSelectAll />と<DataTableSelectRow />のaria-labelで上書きできます。
以下のパーツはすべて、テーブルを共有する <DataTable /> の内側でレンダリングする必要があります。
TanStack Table のオプションを受け取り、テーブルを返します。initialState.pagination で指定しない限り、1 ページは 10 行です。
| プロパティ | 型 | デフォルト |
|---|---|---|
data | TData[] | – |
columnscreateDataTableColumns で作成します。 | ColumnDef[] | – |
getRowId行が移動しても、選択を安定して保ちます。デフォルトは行のインデックスです。 | (row: TData) => string | – |
initialState | Partial<TableState> | { pagination: { pageIndex: 0, pageSize: 10 } } |
statesorting、rowSelection、globalFilter、pagination、columnVisibility を制御します。 | Partial<TableState> | – |
onSortingChange制御可能な各 state には、onRowSelectionChange のような対応するハンドラーがあります。 | OnChangeFn<SortingState> | – |
enableRowSelection | boolean | (row) => boolean | true |
accessor、display、columns を持つ、型付きの列ヘルパーを返します。数値の列に meta: { align: "end" } を設定すると、ヘッダーとセルが揃います。
| プロパティ | 型 | デフォルト |
|---|---|---|
tableuseDataTable が返すテーブル。 | DataTableInstance<TData> | – |
className | string | – |
| 属性 | 説明 |
|---|---|
data-slot="data-table" | すべてのパーツを囲むラッパー。 |
data-slot="data-table-announcer" | 視覚的に非表示のライブリージョン。 |
| プロパティ | 型 | デフォルト |
|---|---|---|
emptyMessage | ReactNode | "No results." |
loading | boolean | false |
loadingRows読み込み中のスケルトン行の数。 | number | 5 |
pinStart開始側の端に固定する列の id。 | string[] | ["select", firstColumnId] |
stickyHeaderコンテナに最大の高さが必要です。 | boolean | false |
containerClassNameスクロールコンテナに適用されます。 | string | – |
swipeSelectチェックボックス上で Shift キーを押しながらドラッグすると、範囲を選択できます。 | boolean | true |
classNametable 要素に適用されます。 | string | – |
| 属性 | 説明 |
|---|---|
data-slot="table-container" | スクロールコンテナ。 |
data-scrolled-start | コンテナが開始側の端からスクロールしているときに付与されます。 |
data-scrolled-end | 終了側の端の方向にスクロールできる余地がある間、付与されます。 |
data-scrolled-top | 行が縦にスクロールされると付与されます。 |
data-swipe-selecting | Shift キーを押しながらのドラッグ中、コンテナに付与されます。 |
data-state="selected" | 選択された行に付与されます。 |
data-row-id | getRowId から返される行 id。 |
data-slot="data-table-loading-row" | 各スケルトン行。 |
data-slot="data-table-empty" | 空の行。 |
検索、View メニュー、独自のフィルター用の、折り返す行。div のすべての props を受け付け、data-slot として data-table-toolbar を持ちます。
| プロパティ | 型 | デフォルト |
|---|---|---|
placeholder | string | "Search…" |
aria-label | string | "Search table" |
clearLabelクリアボタンのアクセシブルな名前。 | string | "Clear search" |
| 属性 | 説明 |
|---|---|
data-slot="data-table-search" | 検索フィールドのラッパー。 |
| プロパティ | 型 | デフォルト |
|---|---|---|
label | string | "View" |
groupLabel | string | "Toggle columns" |
getLabelデフォルトは、列の文字列のヘッダー、または先頭を大文字にした id です。 | (column) => string | – |
非表示にできるすべての列を一覧表示します。除外するには、列に enableHiding: false を設定します。
| 属性 | 説明 |
|---|---|
data-slot="data-table-view-options" | メニューのポップアップ。 |
| プロパティ | 型 | デフォルト |
|---|---|---|
column | Column | – |
title | string | – |
並べ替え可能な列には並べ替えボタンを、それ以外にはプレーンテキストをレンダリングします。
| 属性 | 説明 |
|---|---|
data-slot="data-table-column-header" | ヘッダーのラッパー。 |
data-sorted | 列が並べ替えられている間、並べ替えボタンに付与されます。 |
aria-sort | ヘッダーセルに付与されます: 昇順、降順、またはなし。 |
| プロパティ | 型 | デフォルト |
|---|---|---|
table | Table | – |
aria-label | string | "Select all rows on this page" |
現在のページの行を選択し、一部のみが選択されている場合は不確定状態を表示します。
| プロパティ | 型 | デフォルト |
|---|---|---|
row | Row | – |
aria-label | string | "Select row" |
| プロパティ | 型 | デフォルト |
|---|---|---|
pageSizes | number[] | [10, 20, 50, 100] |
showSelection行数の代わりに、選択された件数を表示します。 | boolean | true |
labelsrowsPerPage、firstPage、previousPage、nextPage、lastPage。 | Partial<DataTablePaginationLabels> | – |
formatSelection | (selected: number, total: number) => ReactNode | "2 of 42 rows selected" |
formatRows | (total: number) => ReactNode | "42 rows" |
formatPage | (page: number, pageCount: number) => ReactNode | "Page 1 of 5" |
| 属性 | 説明 |
|---|---|
data-slot="data-table-pagination" | ページネーションバー。 |
最も近い <DataTable /> からテーブルを返します。ステータスフィルターなど、独自のツールバーコントロールを作るのに使います。
| プロパティ | 型 | デフォルト |
|---|---|---|
stickyHeaderスクロールするコンテナ内で、ヘッダー行を固定します。 | boolean | false |
containerClassNameスクロールコンテナに適用されます。 | string | – |
containerRef | Ref<HTMLDivElement> | – |
| 属性 | 説明 |
|---|---|
data-slot="table" | table 要素。 |
data-sticky-header | stickyHeader がオンのとき、コンテナに付与されます。 |
--table-bg | 行と固定セルの背景。配置先のカードやポップオーバーに従います。 |
| プロパティ | 型 | デフォルト |
|---|---|---|
align終了側に揃えられたセルも、等幅数字を使います。 | "start" | "center" | "end" | "start" |
pinnedテーブルが横にスクロールしても、セルをその場に保ちます。--pin-offset でオフセットします。 | "start" | "end" | – |
pinnedEdgeスクロール中、最後の固定列に柔らかい影を描画します。 | boolean | false |
| 属性 | 説明 |
|---|---|
data-align | 現在の配置。 |
data-pinned | 固定されている場合は start または end。 |
data-pinned-edge | 各側の最後の固定セルに付与されます。 |
--pin-offset | 固定された端からの距離。自動で設定されます。 |
TableHeader、TableBody、TableFooter、TableRow、TableCaption は、対応するテーブル要素をレンダリングし、そのすべての props を受け付けます。
- Buttonすべてのバリアントとサイズのボタンです。読み込み、成功、エラーのフローを内蔵し、高速なリクエストではスピナーを省略します。
- Checkboxチェックが描かれるように表示されるチェックボックスです。中間状態の親、グループ、ホバーを共有するラベルに対応します。
- Skeleton150ms待ってから表示され、包んだコンテンツと同じサイズになり、何も動かさずにコンテンツをフェードインさせるプレースホルダーです。
- Table面のスタイル、折り返しまたはコンパクトなセル、固定ヘッダー、固定列、スクロールのヒントを備えたレスポンシブなテーブル。
- Avatarイニシャルのフォールバック、ステータスバッジ、件数にまとめられる積み重ねグループを備えたユーザー写真です。
- Badge色付きのドットを持つステータスラベル、スライドして閉じる削除可能なタグ、新しい値へ回転するカウントです。