HextaUI

Data table

Gerçek veriler için bir tablo; sıralama, arama, satır seçimi, sabitlenmiş sütunlar, yapışkan başlık ve sayfalama içerir.

MethodCountry
[email protected]paidCardUnited States2026-01-01$5.00
[email protected]pendingPayPalJapan2026-02-02$84.20
[email protected]failedBankGermany2026-03-03$163.40
[email protected]paidApple PayBrazil2026-04-04$242.60
[email protected]pendingCardIndia2026-05-05$321.80
[email protected]failedPayPalUnited States2026-06-06$401.00
[email protected]paidBankJapan2026-07-07$480.10
[email protected]pendingApple PayGermany2026-08-08$559.30
[email protected]failedCardBrazil2026-09-09$638.50
[email protected]paidPayPalIndia2026-01-10$717.70
0 of 42 rows selected
Page 1 of 5
"use client"

import { Badge, BadgeDot } from "@/components/ui/badge"
import {
  createDataTableColumns,
  DataTable,
  DataTableColumnHeader,
  DataTableContent,
  DataTablePagination,
  DataTableSearch,
  DataTableSelectAll,
  DataTableSelectRow,
  DataTableToolbar,
  DataTableViewOptions,
  useDataTable,
} from "@/components/ui/data-table"

type Payment = {
  id: string
  email: string
  status: "paid" | "pending" | "failed"
  amount: number
  method: string
  country: string
  date: string
}

const statuses = ["paid", "pending", "failed"] as const
const methods = ["Card", "PayPal", "Bank", "Apple Pay"]
const countries = ["United States", "Germany", "India", "Japan", "Brazil"]
const names = ["olivia", "jackson", "isabella", "william", "sofia", "liam"]

function makePayments(count: number): Payment[] {
  return Array.from({ length: count }, (_, index) => ({
    id: `pay_${String(index + 1).padStart(4, "0")}`,
    email: `${names[index % names.length]}.${Math.floor(index / names.length) + 1}@example.com`,
    status: statuses[(index * 7) % 3],
    amount: Math.round(((index * 7919) % 100000) / 10) / 10 + 5,
    method: methods[index % methods.length],
    country: countries[(index * 3) % countries.length],
    date: `2026-${String((index % 9) + 1).padStart(2, "0")}-${String((index % 27) + 1).padStart(2, "0")}`,
  }))
}

const payments = makePayments(42)

const currency = new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "USD",
})

const statusVariant = {
  paid: "success",
  pending: "warning",
  failed: "destructive",
} as const

const helper = createDataTableColumns<Payment>()

const columns = helper.columns([
  helper.display({
    id: "select",
    header: ({ table }) => <DataTableSelectAll table={table} />,
    cell: ({ row }) => <DataTableSelectRow row={row} />,
    enableSorting: false,
    enableHiding: false,
  }),
  helper.accessor("email", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Email" />
    ),
  }),
  helper.accessor("status", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Status" />
    ),
    cell: ({ getValue }) => {
      const status = getValue()
      return (
        <Badge variant={statusVariant[status]}>
          <BadgeDot />
          <span className="capitalize">{status}</span>
        </Badge>
      )
    },
  }),
  helper.accessor("method", { header: "Method" }),
  helper.accessor("country", { header: "Country" }),
  helper.accessor("date", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Date" />
    ),
  }),
  helper.accessor("amount", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Amount" />
    ),
    cell: ({ getValue }) => currency.format(getValue()),
    meta: { align: "end" },
  }),
])

export function DataTableDemo() {
  const table = useDataTable({
    data: payments,
    columns,
    getRowId: (row) => row.id,
  })

  return (
    <DataTable table={table}>
      <DataTableToolbar>
        <DataTableSearch placeholder="Search payments…" />
        <DataTableViewOptions />
      </DataTableToolbar>
      <DataTableContent emptyMessage="No payments match your search." />
      <DataTablePagination />
    </DataTable>
  )
}
pnpm dlx shadcn@latest add https://hextaui.com/r/data-table.json

Bileşeni, HextaUI tema token'larını ve bileşenin bağımlı olduğu tüm HextaUI bileşenlerini ekler.

Data table, sıralama, filtreleme, sayfalama, seçim ve sütun görünürlüğü özellikleri hazır bağlanmış TanStack Table v9'dur. Sütunları createDataTableColumns ile bir kez tanımlayın, tabloyu useDataTable ile oluşturun, sonra ihtiyaç duyduğunuz parçaları birleştirin.

import {
  createDataTableColumns,
  DataTable,
  DataTableColumnHeader,
  DataTableContent,
  DataTablePagination,
  DataTableSearch,
  DataTableSelectAll,
  DataTableSelectRow,
  DataTableToolbar,
  DataTableViewOptions,
  useDataTable,
} from "@/components/ui/data-table"
type Payment = { id: string; email: string; amount: number }

const helper = createDataTableColumns<Payment>()

const columns = helper.columns([
  helper.display({
    id: "select",
    header: ({ table }) => <DataTableSelectAll table={table} />,
    cell: ({ row }) => <DataTableSelectRow row={row} />,
    enableSorting: false,
    enableHiding: false,
  }),
  helper.accessor("email", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Email" />
    ),
  }),
  helper.accessor("amount", {
    header: "Amount",
    meta: { align: "end" },
  }),
])
export function Payments({ data }: { data: Payment[] }) {
  const table = useDataTable({
    data,
    columns,
    getRowId: (row) => row.id,
  })

  return (
    <DataTable table={table}>
      <DataTableToolbar>
        <DataTableSearch placeholder="Search payments…" />
        <DataTableViewOptions />
      </DataTableToolbar>
      <DataTableContent />
      <DataTablePagination />
    </DataTable>
  )
}

Sahip olmak istediğiniz herhangi bir TanStack state'ini, örneğin sıralama veya satır seçimini, değişim işleyicisiyle birlikte geçin.

const [sorting, setSorting] = React.useState([{ id: "date", desc: true }])

const table = useDataTable({
  data,
  columns,
  state: { sorting },
  onSortingChange: setSorting,
})
DataTable
├── DataTableToolbar
│   ├── DataTableSearch
│   └── DataTableViewOptions
├── DataTableContent
└── DataTablePagination

DataTableColumnHeader, DataTableSelectAll ve DataTableSelectRow, bir sütunun başlığı veya hücresi olarak sütun tanımlarınıza girer.

Düz tablo

Data table'ın üzerine kurulduğu düz <Table /> parçaları. Statik veri için bir başlık ve alt toplamla tek başlarına kullanın.

import {
  Table,
  TableBody,
  TableCaption,
  TableCell,
  TableFooter,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"

const invoices = [
  { id: "INV001", status: "Paid", method: "Credit card", amount: 250 },
  { id: "INV002", status: "Pending", method: "PayPal", amount: 150 },
  { id: "INV003", status: "Unpaid", method: "Bank transfer", amount: 350 },
  { id: "INV004", status: "Paid", method: "Credit card", amount: 450 },
]

const currency = new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "USD",
})

export function TableDemo() {
  const total = invoices.reduce((sum, invoice) => sum + invoice.amount, 0)

  return (
    <Table>
      <TableCaption>A list of your recent invoices.</TableCaption>
      <TableHeader>
        <TableRow>
          <TableHead>Invoice</TableHead>
          <TableHead>Status</TableHead>
          <TableHead>Method</TableHead>
          <TableHead align="end">Amount</TableHead>
        </TableRow>
      </TableHeader>
      <TableBody>
        {invoices.map((invoice) => (
          <TableRow key={invoice.id}>
            <TableCell>{invoice.id}</TableCell>
            <TableCell>{invoice.status}</TableCell>
            <TableCell>{invoice.method}</TableCell>
            <TableCell align="end">{currency.format(invoice.amount)}</TableCell>
          </TableRow>
        ))}
      </TableBody>
      <TableFooter>
        <TableRow>
          <TableCell colSpan={3}>Total</TableCell>
          <TableCell align="end">{currency.format(total)}</TableCell>
        </TableRow>
      </TableFooter>
    </Table>
  )
}

Yükleniyor

loading ile skeleton satırlar gerçek satırlarla aynı alanı doldurur; böylece veri geldiğinde hiçbir şey zıplamaz. Bu sırada tablo aria-busy olarak işaretlenir.

"use client"

import * as React from "react"

import { Badge, BadgeDot } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import {
  createDataTableColumns,
  DataTable,
  DataTableColumnHeader,
  DataTableContent,
  DataTablePagination,
  DataTableSearch,
  DataTableSelectAll,
  DataTableSelectRow,
  DataTableToolbar,
  DataTableViewOptions,
  useDataTable,
} from "@/components/ui/data-table"

type Payment = {
  id: string
  email: string
  status: "paid" | "pending" | "failed"
  amount: number
  method: string
  country: string
  date: string
}

const statuses = ["paid", "pending", "failed"] as const
const methods = ["Card", "PayPal", "Bank", "Apple Pay"]
const countries = ["United States", "Germany", "India", "Japan", "Brazil"]
const names = ["olivia", "jackson", "isabella", "william", "sofia", "liam"]

function makePayments(count: number): Payment[] {
  return Array.from({ length: count }, (_, index) => ({
    id: `pay_${String(index + 1).padStart(4, "0")}`,
    email: `${names[index % names.length]}.${Math.floor(index / names.length) + 1}@example.com`,
    status: statuses[(index * 7) % 3],
    amount: Math.round(((index * 7919) % 100000) / 10) / 10 + 5,
    method: methods[index % methods.length],
    country: countries[(index * 3) % countries.length],
    date: `2026-${String((index % 9) + 1).padStart(2, "0")}-${String((index % 27) + 1).padStart(2, "0")}`,
  }))
}

const payments = makePayments(5)

const currency = new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "USD",
})

const statusVariant = {
  paid: "success",
  pending: "warning",
  failed: "destructive",
} as const

const helper = createDataTableColumns<Payment>()

const columns = helper.columns([
  helper.display({
    id: "select",
    header: ({ table }) => <DataTableSelectAll table={table} />,
    cell: ({ row }) => <DataTableSelectRow row={row} />,
    enableSorting: false,
    enableHiding: false,
  }),
  helper.accessor("email", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Email" />
    ),
  }),
  helper.accessor("status", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Status" />
    ),
    cell: ({ getValue }) => {
      const status = getValue()
      return (
        <Badge variant={statusVariant[status]}>
          <BadgeDot />
          <span className="capitalize">{status}</span>
        </Badge>
      )
    },
  }),
  helper.accessor("method", { header: "Method" }),
  helper.accessor("country", { header: "Country" }),
  helper.accessor("date", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Date" />
    ),
  }),
  helper.accessor("amount", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Amount" />
    ),
    cell: ({ getValue }) => currency.format(getValue()),
    meta: { align: "end" },
  }),
])

export function DataTableLoading() {
  const [loading, setLoading] = React.useState(true)
  const table = useDataTable({
    data: payments,
    columns,
    getRowId: (row) => row.id,
  })

  return (
    <div className="flex w-full flex-col items-start gap-3">
      <Button
        variant="outline"
        size="sm"
        onClick={() => setLoading((value) => !value)}
      >
        {loading ? "Finish loading" : "Load again"}
      </Button>
      <DataTable table={table}>
        <DataTableToolbar>
          <DataTableSearch placeholder="Search payments…" />
          <DataTableViewOptions />
        </DataTableToolbar>
        <DataTableContent loading={loading} />
        <DataTablePagination />
      </DataTable>
    </div>
  )
}

Empty

emptyMessage, veri olmadığında veya hiçbir şey aramayla eşleşmediğinde gövdeyi doldurur.

"use client"

import { Badge, BadgeDot } from "@/components/ui/badge"
import {
  createDataTableColumns,
  DataTable,
  DataTableColumnHeader,
  DataTableContent,
  DataTablePagination,
  DataTableSearch,
  DataTableSelectAll,
  DataTableSelectRow,
  DataTableToolbar,
  DataTableViewOptions,
  useDataTable,
} from "@/components/ui/data-table"

type Payment = {
  id: string
  email: string
  status: "paid" | "pending" | "failed"
  amount: number
  method: string
  country: string
  date: string
}

const statuses = ["paid", "pending", "failed"] as const
const methods = ["Card", "PayPal", "Bank", "Apple Pay"]
const countries = ["United States", "Germany", "India", "Japan", "Brazil"]
const names = ["olivia", "jackson", "isabella", "william", "sofia", "liam"]

function makePayments(count: number): Payment[] {
  return Array.from({ length: count }, (_, index) => ({
    id: `pay_${String(index + 1).padStart(4, "0")}`,
    email: `${names[index % names.length]}.${Math.floor(index / names.length) + 1}@example.com`,
    status: statuses[(index * 7) % 3],
    amount: Math.round(((index * 7919) % 100000) / 10) / 10 + 5,
    method: methods[index % methods.length],
    country: countries[(index * 3) % countries.length],
    date: `2026-${String((index % 9) + 1).padStart(2, "0")}-${String((index % 27) + 1).padStart(2, "0")}`,
  }))
}

const payments: Payment[] = []

const currency = new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "USD",
})

const statusVariant = {
  paid: "success",
  pending: "warning",
  failed: "destructive",
} as const

const helper = createDataTableColumns<Payment>()

const columns = helper.columns([
  helper.display({
    id: "select",
    header: ({ table }) => <DataTableSelectAll table={table} />,
    cell: ({ row }) => <DataTableSelectRow row={row} />,
    enableSorting: false,
    enableHiding: false,
  }),
  helper.accessor("email", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Email" />
    ),
  }),
  helper.accessor("status", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Status" />
    ),
    cell: ({ getValue }) => {
      const status = getValue()
      return (
        <Badge variant={statusVariant[status]}>
          <BadgeDot />
          <span className="capitalize">{status}</span>
        </Badge>
      )
    },
  }),
  helper.accessor("method", { header: "Method" }),
  helper.accessor("country", { header: "Country" }),
  helper.accessor("date", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Date" />
    ),
  }),
  helper.accessor("amount", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Amount" />
    ),
    cell: ({ getValue }) => currency.format(getValue()),
    meta: { align: "end" },
  }),
])

export function DataTableEmpty() {
  const table = useDataTable({
    data: payments,
    columns,
    getRowId: (row) => row.id,
  })

  return (
    <DataTable table={table}>
      <DataTableToolbar>
        <DataTableSearch placeholder="Search payments…" />
        <DataTableViewOptions />
      </DataTableToolbar>
      <DataTableContent emptyMessage="No payments yet." />
      <DataTablePagination />
    </DataTable>
  )
}

containerClassName ile kapsayıcıya azami bir yükseklik verin ve stickyHeader ayarlayın. Başlık yerinde kalır ve satırlar altından kaydığında ince bir çizgi kazanır. Checkbox'lar üzerinde Shift ile sürüklemek, kenarına yaklaştıkça kutuyu kaydırır.

"use client"

import { Badge, BadgeDot } from "@/components/ui/badge"
import {
  createDataTableColumns,
  DataTable,
  DataTableColumnHeader,
  DataTableContent,
  DataTablePagination,
  DataTableSearch,
  DataTableSelectAll,
  DataTableSelectRow,
  DataTableToolbar,
  DataTableViewOptions,
  useDataTable,
} from "@/components/ui/data-table"

type Payment = {
  id: string
  email: string
  status: "paid" | "pending" | "failed"
  amount: number
  method: string
  country: string
  date: string
}

const statuses = ["paid", "pending", "failed"] as const
const methods = ["Card", "PayPal", "Bank", "Apple Pay"]
const countries = ["United States", "Germany", "India", "Japan", "Brazil"]
const names = ["olivia", "jackson", "isabella", "william", "sofia", "liam"]

function makePayments(count: number): Payment[] {
  return Array.from({ length: count }, (_, index) => ({
    id: `pay_${String(index + 1).padStart(4, "0")}`,
    email: `${names[index % names.length]}.${Math.floor(index / names.length) + 1}@example.com`,
    status: statuses[(index * 7) % 3],
    amount: Math.round(((index * 7919) % 100000) / 10) / 10 + 5,
    method: methods[index % methods.length],
    country: countries[(index * 3) % countries.length],
    date: `2026-${String((index % 9) + 1).padStart(2, "0")}-${String((index % 27) + 1).padStart(2, "0")}`,
  }))
}

const payments = makePayments(1000)

const currency = new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "USD",
})

const statusVariant = {
  paid: "success",
  pending: "warning",
  failed: "destructive",
} as const

const helper = createDataTableColumns<Payment>()

const columns = helper.columns([
  helper.display({
    id: "select",
    header: ({ table }) => <DataTableSelectAll table={table} />,
    cell: ({ row }) => <DataTableSelectRow row={row} />,
    enableSorting: false,
    enableHiding: false,
  }),
  helper.accessor("email", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Email" />
    ),
  }),
  helper.accessor("status", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Status" />
    ),
    cell: ({ getValue }) => {
      const status = getValue()
      return (
        <Badge variant={statusVariant[status]}>
          <BadgeDot />
          <span className="capitalize">{status}</span>
        </Badge>
      )
    },
  }),
  helper.accessor("method", { header: "Method" }),
  helper.accessor("country", { header: "Country" }),
  helper.accessor("date", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Date" />
    ),
  }),
  helper.accessor("amount", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Amount" />
    ),
    cell: ({ getValue }) => currency.format(getValue()),
    meta: { align: "end" },
  }),
])

export function DataTableStickyHeader() {
  const table = useDataTable({
    data: payments,
    columns,
    getRowId: (row) => row.id,
    initialState: { pagination: { pageIndex: 0, pageSize: 100 } },
  })

  return (
    <DataTable table={table}>
      <DataTableToolbar>
        <DataTableSearch placeholder="Search 1,000 payments…" />
        <DataTableViewOptions />
      </DataTableToolbar>
      <DataTableContent stickyHeader containerClassName="max-h-80" />
      <DataTablePagination />
    </DataTable>
  )
}

Sabitlenmiş sütunlar

Seçim sütunu ve ilk veri sütunu varsayılan olarak sabitlenir. Kendinizinkini pinStart ile seçin. Tablo yana kaydığında kenarı yumuşak bir gölge işaretler.

"use client"

import { Badge, BadgeDot } from "@/components/ui/badge"
import {
  createDataTableColumns,
  DataTable,
  DataTableColumnHeader,
  DataTableContent,
  DataTablePagination,
  DataTableSearch,
  DataTableSelectAll,
  DataTableSelectRow,
  DataTableToolbar,
  DataTableViewOptions,
  useDataTable,
} from "@/components/ui/data-table"

type Payment = {
  id: string
  email: string
  status: "paid" | "pending" | "failed"
  amount: number
  method: string
  country: string
  date: string
}

const statuses = ["paid", "pending", "failed"] as const
const methods = ["Card", "PayPal", "Bank", "Apple Pay"]
const countries = ["United States", "Germany", "India", "Japan", "Brazil"]
const names = ["olivia", "jackson", "isabella", "william", "sofia", "liam"]

function makePayments(count: number): Payment[] {
  return Array.from({ length: count }, (_, index) => ({
    id: `pay_${String(index + 1).padStart(4, "0")}`,
    email: `${names[index % names.length]}.${Math.floor(index / names.length) + 1}@example.com`,
    status: statuses[(index * 7) % 3],
    amount: Math.round(((index * 7919) % 100000) / 10) / 10 + 5,
    method: methods[index % methods.length],
    country: countries[(index * 3) % countries.length],
    date: `2026-${String((index % 9) + 1).padStart(2, "0")}-${String((index % 27) + 1).padStart(2, "0")}`,
  }))
}

const payments = makePayments(12)

const currency = new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "USD",
})

const statusVariant = {
  paid: "success",
  pending: "warning",
  failed: "destructive",
} as const

const helper = createDataTableColumns<Payment>()

const columns = helper.columns([
  helper.display({
    id: "select",
    header: ({ table }) => <DataTableSelectAll table={table} />,
    cell: ({ row }) => <DataTableSelectRow row={row} />,
    enableSorting: false,
    enableHiding: false,
  }),
  helper.accessor("email", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Email" />
    ),
  }),
  helper.accessor("status", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Status" />
    ),
    cell: ({ getValue }) => {
      const status = getValue()
      return (
        <Badge variant={statusVariant[status]}>
          <BadgeDot />
          <span className="capitalize">{status}</span>
        </Badge>
      )
    },
  }),
  helper.accessor("method", { header: "Method" }),
  helper.accessor("country", { header: "Country" }),
  helper.accessor("date", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Date" />
    ),
  }),
  helper.accessor("amount", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Amount" />
    ),
    cell: ({ getValue }) => currency.format(getValue()),
    meta: { align: "end" },
  }),
])

export function DataTablePinnedColumns() {
  const table = useDataTable({
    data: payments,
    columns,
    getRowId: (row) => row.id,
  })

  return (
    <div className="w-full max-w-md">
      <DataTable table={table}>
        <DataTableToolbar>
          <DataTableSearch placeholder="Search payments…" />
          <DataTableViewOptions />
        </DataTableToolbar>
        <DataTableContent pinStart={["select", "email", "status"]} />
        <DataTablePagination />
      </DataTable>
    </div>
  )
}

Sağdan sola

Her etiket ve sayı labels ve biçim fonksiyonlarıyla değiştirilebilir. Sayfalama okları ve sabitlenmiş sütunlar yönle birlikte ters döner.

"use client"

import { Badge, BadgeDot } from "@/components/ui/badge"
import {
  createDataTableColumns,
  DataTable,
  DataTableColumnHeader,
  DataTableContent,
  DataTablePagination,
  DataTableSearch,
  DataTableSelectAll,
  DataTableSelectRow,
  DataTableToolbar,
  DataTableViewOptions,
  useDataTable,
} from "@/components/ui/data-table"

type Payment = {
  id: string
  email: string
  status: "paid" | "pending" | "failed"
  amount: number
  method: string
  country: string
  date: string
}

const statuses = ["paid", "pending", "failed"] as const
const methods = ["Card", "PayPal", "Bank", "Apple Pay"]
const countries = ["United States", "Germany", "India", "Japan", "Brazil"]
const names = ["olivia", "jackson", "isabella", "william", "sofia", "liam"]

function makePayments(count: number): Payment[] {
  return Array.from({ length: count }, (_, index) => ({
    id: `pay_${String(index + 1).padStart(4, "0")}`,
    email: `${names[index % names.length]}.${Math.floor(index / names.length) + 1}@example.com`,
    status: statuses[(index * 7) % 3],
    amount: Math.round(((index * 7919) % 100000) / 10) / 10 + 5,
    method: methods[index % methods.length],
    country: countries[(index * 3) % countries.length],
    date: `2026-${String((index % 9) + 1).padStart(2, "0")}-${String((index % 27) + 1).padStart(2, "0")}`,
  }))
}

const payments = makePayments(6)

const currency = new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "USD",
})

const statusVariant = {
  paid: "success",
  pending: "warning",
  failed: "destructive",
} as const

const helper = createDataTableColumns<Payment>()

const columns = helper.columns([
  helper.display({
    id: "select",
    header: ({ table }) => <DataTableSelectAll table={table} />,
    cell: ({ row }) => <DataTableSelectRow row={row} />,
    enableSorting: false,
    enableHiding: false,
  }),
  helper.accessor("email", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Email" />
    ),
  }),
  helper.accessor("status", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Status" />
    ),
    cell: ({ getValue }) => {
      const status = getValue()
      return (
        <Badge variant={statusVariant[status]}>
          <BadgeDot />
          <span className="capitalize">{status}</span>
        </Badge>
      )
    },
  }),
  helper.accessor("method", { header: "Method" }),
  helper.accessor("country", { header: "Country" }),
  helper.accessor("date", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Date" />
    ),
  }),
  helper.accessor("amount", {
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Amount" />
    ),
    cell: ({ getValue }) => currency.format(getValue()),
    meta: { align: "end" },
  }),
])

const arabicNumber = new Intl.NumberFormat("ar")

export function DataTableRtl() {
  const table = useDataTable({
    data: payments,
    columns,
    getRowId: (row) => row.id,
  })

  return (
    <div dir="rtl" className="w-full">
      <DataTable table={table}>
        <DataTableToolbar>
          <DataTableSearch placeholder="ابحث في المدفوعات…" />
          <DataTableViewOptions label="عرض" groupLabel="إظهار الأعمدة" />
        </DataTableToolbar>
        <DataTableContent emptyMessage="لا توجد نتائج." />
        <DataTablePagination
          labels={{
            rowsPerPage: "صفوف في الصفحة",
            firstPage: "الصفحة الأولى",
            previousPage: "الصفحة السابقة",
            nextPage: "الصفحة التالية",
            lastPage: "الصفحة الأخيرة",
          }}
          formatSelection={(selected, total) =>
            `تم تحديد ${arabicNumber.format(selected)} من ${arabicNumber.format(total)}`
          }
          formatPage={(page, count) =>
            `صفحة ${arabicNumber.format(page)} من ${arabicNumber.format(count)}`
          }
        />
      </DataTable>
    </div>
  )
}
  • Artan sıralamak için sıralanabilir bir başlığa tıklayın, azalan için tekrar, temizlemek için üçüncü kez tıklayın. İkincil bir sıralama eklemek için başka bir başlığa Shift ile tıklayın.
  • Bir satır checkbox'ına Shift ile tıklamak, onunla en son tıkladığınız arasındaki her satırı seçer. Bir aralığı tek harekette seçmek veya temizlemek için Shift'e basılı tutup checkbox'lar üzerinde sürükleyin.
  • Arama, seçim sütunu hariç tüm sütunlarla eşleşir ve ilk sayfaya döner.
  • Sütunları View menüsünden gizlemek menüyü açık tutar; böylece birkaçını aynı anda açıp kapatabilirsiniz.
TuşAction
TabArama, View menüsü, sıralanabilir başlıklar, satır checkbox'ları ve sayfalama arasında gezinir.
EnterSpaceOdaktaki başlığa göre sıralar.
SpaceOdaktaki checkbox'ı açıp kapatır.
EscMetin varsa aramayı temizler.
  • Sıralanabilir başlıklar aria-sort taşır ve kibar (polite) bir canlı bölge yeni sıralamayı, yazdıktan kısa süre sonra da sonuç sayısını duyurur.
  • Sayfa göstergesi bir canlı bölgedir; böylece ekran okuyucular next veya previous'a bastıktan sonra yeni sayfayı duyar.
  • Checkbox'ların varsayılan olarak etiketleri vardır. <DataTableSelectAll /> ve <DataTableSelectRow /> üzerinde aria-label ile geçersiz kılın.

Aşağıdaki her parça, tabloyu onlarla paylaşan <DataTable /> içinde render edilmelidir.

TanStack Table seçeneklerini alır ve tabloyu döndürür. initialState.pagination aksini söylemedikçe sayfalar 10 satır tutar.

PropTürVarsayılan
data
TData[]–
columnsBunları createDataTableColumns ile oluşturun.
ColumnDef[]–
getRowIdSatırlar hareket ettiğinde seçimi kararlı tutar. Varsayılan olarak satır dizinidir.
(row: TData) => string–
initialState
Partial<TableState>{ pagination: { pageIndex: 0, pageSize: 10 } }
statesorting, rowSelection, globalFilter, pagination veya columnVisibility'yi kontrol edin.
Partial<TableState>–
onSortingChangeKontrol edilebilir her state'in, onRowSelectionChange gibi eşleşen bir işleyicisi vardır.
OnChangeFn<SortingState>–
enableRowSelection
boolean | (row) => booleantrue

accessor, display ve columns içeren tipli bir sütun yardımcısı döndürür. Başlığı ve hücreleri hizalamak için sayısal sütunlarda meta: { align: "end" } ayarlayın.

PropTürVarsayılan
tableuseDataTable'ın döndürdüğü tablo.
DataTableInstance<TData>–
className
string–
ÖznitelikAçıklama
data-slot="data-table"Her parçanın çevresindeki sarmalayıcı.
data-slot="data-table-announcer"Görsel olarak gizli canlı bölge.
PropTürVarsayılan
emptyMessage
ReactNode"No results."
loading
booleanfalse
loadingRowsYükleme sırasındaki skeleton satır sayısı.
number5
pinStartBaşlangıç kenarına sabitlenecek sütun id'leri.
string[]["select", firstColumnId]
stickyHeaderKapsayıcıda azami bir yükseklik gerekir.
booleanfalse
containerClassNameKaydırma kapsayıcısına uygulanır.
string–
swipeSelectBir aralığı seçmek için checkbox'lar üzerinde Shift ile sürükleyin.
booleantrue
classNameTablo öğesine uygulanır.
string–
ÖznitelikAçıklama
data-slot="table-container"Kaydırma kapsayıcısı.
data-scrolled-startBaşlangıç kenarından uzaklaşıldığında kapsayıcıda bulunur.
data-scrolled-endSon kenara doğru kaydırılacak daha fazla şey olduğunda bulunur.
data-scrolled-topSatırlar dikey kaydırıldıktan sonra bulunur.
data-swipe-selectingShift ile sürükleme sırasında kapsayıcıda bulunur.
data-state="selected"Seçili satırlarda bulunur.
data-row-idgetRowId'den gelen satır id'si.
data-slot="data-table-loading-row"Her skeleton satırı.
data-slot="data-table-empty"Boş satır.

Arama, View menüsü ve kendi filtreleriniz için sarmalayan bir satır. Tüm div prop'larını kabul eder ve data-slot olarak data-table-toolbar taşır.

PropTürVarsayılan
placeholder
string"Search…"
aria-label
string"Search table"
clearLabelTemizle düğmesinin erişilebilir adı.
string"Clear search"
ÖznitelikAçıklama
data-slot="data-table-search"Arama alanı sarmalayıcısı.
PropTürVarsayılan
label
string"View"
groupLabel
string"Toggle columns"
getLabelVarsayılan olarak sütunun string başlığıdır veya baş harfi büyük id'sidir.
(column) => string–

Gizlenebilen her sütunu listeler. Bir sütunu dışarıda bırakmak için üzerinde enableHiding: false ayarlayın.

ÖznitelikAçıklama
data-slot="data-table-view-options"Menü popup'ı.
PropTürVarsayılan
column
Column–
title
string–

Sıralanabilir sütunlar için bir sıralama düğmesi, diğerleri için düz metin render eder.

ÖznitelikAçıklama
data-slot="data-table-column-header"Başlık sarmalayıcısı.
data-sortedSütun sıralıyken sıralama düğmesinde bulunur.
aria-sortBaşlık hücresinde: artan, azalan veya yok.
PropTürVarsayılan
table
Table–
aria-label
string"Select all rows on this page"

Geçerli sayfadaki satırları seçer ve yalnızca bazıları seçiliyken belirsiz (indeterminate) bir durum gösterir.

PropTürVarsayılan
row
Row–
aria-label
string"Select row"
PropTürVarsayılan
pageSizes
number[][10, 20, 50, 100]
showSelectionSatır sayısı yerine seçili sayıyı gösterin.
booleantrue
labelsrowsPerPage, firstPage, previousPage, nextPage ve 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"
ÖznitelikAçıklama
data-slot="data-table-pagination"Sayfalama çubuğu.

En yakın <DataTable /> bileşeninden tabloyu döndürür. Bir durum filtresi gibi kendi araç çubuğu kontrollerinizi oluşturmak için kullanın.

PropTürVarsayılan
stickyHeaderBaşlık satırını kayan bir kapsayıcının içinde sabitler.
booleanfalse
containerClassNameKaydırma kapsayıcısına uygulanır.
string–
containerRef
Ref<HTMLDivElement>–
ÖznitelikAçıklama
data-slot="table"Tablo öğesi.
data-sticky-headerstickyHeader açıkken kapsayıcıda bulunur.
--table-bgSatır ve sabitlenmiş hücre arka planı. İçinde bulunduğu kartı veya popover'ı izler.
PropTürVarsayılan
alignSona hizalı hücreler de tabular rakamlar kullanır.
"start" | "center" | "end""start"
pinnedTablo yana kayarken hücreyi yerinde tutar. --pin-offset ile kaydırın.
"start" | "end"–
pinnedEdgeKaydırılırken son sabitlenmiş sütunda yumuşak bir gölge çizer.
booleanfalse
ÖznitelikAçıklama
data-alignGeçerli hizalama.
data-pinnedSabitlendiğinde start veya end.
data-pinned-edgeBir tarafın son sabitlenmiş hücresinde bulunur.
--pin-offsetSabitlenen kenardan uzaklık; sizin için ayarlanır.

TableHeader, TableBody, TableFooter, TableRow ve TableCaption eşleşen tablo öğelerini render eder ve onların tüm prop'larını kabul eder.