Caroa UI

DataTable

ソート・フィルタ・検索・ページネーション対応のデータテーブル。

インポート

'use client'
 
import { DataTable } from '@caroainc/ui-components/client'
import type { DataTableColumn, FilterItem } from '@caroainc/ui-components/client'

基本的な使い方

Loading...
interface User {
  id: number
  name: string
  email: string
  role: string
  status: string
}
 
const columns: DataTableColumn<User>[] = [
  { id: 'name', header: '名前', accessorKey: 'name', sortable: true },
  { id: 'email', header: 'メール', accessorKey: 'email' },
  { id: 'role', header: '役割', accessorKey: 'role' },
  {
    id: 'status',
    header: 'ステータス',
    accessorKey: 'status',
    cell: (row) => <Badge variant="success">{row.status}</Badge>,
  },
]
 
<DataTable columns={columns} data={data} hideSearch />

検索・ソート付き

ヘッダーをクリックしてソート、検索ボックスでフィルタリングできます。

Loading...
const columns: DataTableColumn<User>[] = [
  { id: 'name', header: '名前', accessorKey: 'name', sortable: true },
  { id: 'email', header: 'メール', accessorKey: 'email', sortable: true },
  { id: 'role', header: '役割', accessorKey: 'role', sortable: true },
  { id: 'status', header: 'ステータス', accessorKey: 'status' },
]
 
<DataTable
  columns={columns}
  data={data}
  searchPlaceholder="名前やメールで検索..."
/>

フィルター付き

フィルターボタンで条件付きフィルタリングができます。

Loading...
const filterItems: FilterItem<User>[] = [
  {
    id: 'status',
    field: 'status',
    label: 'ステータス',
    type: 'text',
    conditions: [
      { label: '有効', condition: { type: 'equals', value: 'active' } },
      { label: '無効', condition: { type: 'equals', value: 'inactive' } },
      { label: '保留中', condition: { type: 'equals', value: 'pending' } },
    ],
  },
  {
    id: 'role',
    field: 'role',
    label: '役割',
    type: 'text',
    conditions: [
      { label: '管理者', condition: { type: 'equals', value: '管理者' } },
      { label: '編集者', condition: { type: 'equals', value: '編集者' } },
      { label: 'メンバー', condition: { type: 'equals', value: 'メンバー' } },
    ],
  },
]
 
<DataTable
  columns={columns}
  data={data}
  filterItems={filterItems}
  searchPlaceholder="検索..."
/>

ページネーション付き

Loading...
<DataTable
  columns={columns}
  data={paginatedData}
  pagination={{
    page: 1,
    limit: 10,
    total: 100,
    totalPages: 10,
  }}
  onPageChange={(page) => setPage(page)}
/>

行アクション付き

各行にアクションボタンを追加できます。

Loading...
const rowActions = (row: User) => (
  <DropdownMenu>
    <DropdownMenuTrigger asChild>
      <Button variant="ghost" size="sm" shape="circle">
        <Icon name="MoreHorizontal" size="sm" />
      </Button>
    </DropdownMenuTrigger>
    <DropdownMenuContent align="end">
      <DropdownMenuItem>
        <Icon name="Eye" size="sm" />
        詳細を見る
      </DropdownMenuItem>
      <DropdownMenuItem>
        <Icon name="Pencil" size="sm" />
        編集
      </DropdownMenuItem>
      <DropdownMenuSeparator />
      <DropdownMenuItem className="text-destructive">
        <Icon name="Trash2" size="sm" />
        削除
      </DropdownMenuItem>
    </DropdownMenuContent>
  </DropdownMenu>
)
 
<DataTable columns={columns} data={data} rowActions={rowActions} />

カスタムアクション付き

検索ボックスの横にカスタムボタンを追加できます。

Loading...
const customActions = (
  <Button size="sm">
    <Icon name="Plus" size="sm" />
    新規追加
  </Button>
)
 
<DataTable
  columns={columns}
  data={data}
  customActions={customActions}
  searchPlaceholder="検索..."
/>

空状態

データがない場合のカスタム表示。

Loading...
<DataTable
  columns={columns}
  data={[]}
  emptyState={{
    icon: <Icon name="Users" size="xl" className="text-muted-foreground mb-4" />,
    title: 'ユーザーがいません',
    description: '新しいユーザーを追加してください',
    action: (
      <Button>
        <Icon name="Plus" size="sm" />
        ユーザーを追加
      </Button>
    ),
  }}
/>

ローディング状態

Loading...
<DataTable columns={columns} data={[]} loading />

Props

DataTable

PropTypeDefaultDescription
columns*DataTableColumn[]-カラム定義の配列
data*T[]-テーブルに表示するデータ
filterItemsFilterItem[]-フィルター項目の配列
onFiltersChange(filters: ActiveFilter[]) => void-フィルター変更時のコールバック
searchPlaceholderstring'検索...'検索ボックスのプレースホルダー
onSearchChange(search: string) => void-検索文字列変更時のコールバック
hideSearchbooleanfalse検索ボックスを非表示にする
paginationPaginationInfo-ページネーション設定
onPageChange(page: number) => void-ページ変更時のコールバック
loadingbooleanfalseローディング状態
emptyState{ icon, title, description, action }-データがない場合の表示設定
customActionsReactNode-検索ボックス横のカスタムアクション
onRowClick(item: T) => void-行クリック時のコールバック
rowActions(item: T) => ReactNode-各行のアクションレンダラー
classNamestring-追加のクラス名

DataTableColumn

PropTypeDefaultDescription
id*string-カラムの一意な識別子
header*string-ヘッダーに表示するテキスト
accessorKeykeyof T-データオブジェクトのキー
cell(data: T) => ReactNode-カスタムセルレンダラー
width'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'auto'-カラムの幅
sortablebooleanfalseソート可能にする
align'left' | 'center' | 'right''left'テキストの配置

FilterItem

PropTypeDefaultDescription
id*string-フィルターの一意な識別子
label*string-フィルターのラベル
field*keyof T-フィルター対象のフィールド
type'text' | 'email' | 'phone' | 'url' | 'number' | 'date'-フィルタータイプ
iconReactNode-カスタムアイコン
conditionsArray<{ label, condition }>-フィルター条件の配列

PaginationInfo

PropTypeDefaultDescription
page*number-現在のページ番号(1始まり)
limit*number-1ページあたりの件数
total*number-総件数
totalPages*number-総ページ数

On this page