Skip to Content
DataTable

DataTable

Easy to use table and datagrids built using TanStack Table .

#

Documentation

#

Install

Install the required peer dependencies to start using this component:

npm install @tanstack/react-table

#

Usage

Use the table prop to pass a table instance returned from useReactTable() hook. At minimum make sure to include columns, data, and getCoreRowModel when using the hook.

ArthurMorgansuccess$20
JohnMarstonprocessing$12.75
MicahBellfailed$1.25
"use client"; import { DataTable, DataTableBody } from "@optiaxiom/react"; import { getCoreRowModel, useReactTable } from "@tanstack/react-table"; import { columns } from "./columns"; import { data } from "./data"; export function App() { const table = useReactTable({ columns, data, getCoreRowModel: getCoreRowModel(), }); return ( <DataTable table={table}> <DataTableBody /> </DataTable> ); }

#

Anatomy

import { DataTable, DataTableBody, DataTableFooter } from "@optiaxiom/react"; export default () => ( <DataTable> <DataTableBody> <DataTableAction /> <DataTableCheckbox /> <DataTableLabel /> </DataTableBody> <DataTableFooter /> </DataTable> );

#

Vertical scrolling

Headers in DataTable are sticky by default. Set a height on the component to allow scrolling vertically when a large number of rows are present.

1KrystelWuckert$696.47
2FayeBeier$684.83
3CloydNicolas$398.04
4NathanFarrell$849.44
5HarveyKautzer$293.71
6TeaganBuckridge$312.26
7DestanyLeannon-Moore$317.28
8JohnnyJohnson$120.62
9MarcoPadberg$681.30
10DeliaBoyer$842.35
11AgustinCronin$885.33
12MaxwellWalsh$153.07
13EmelieZiemann$841.67
14MaxwellFisher$355.91
15BransonOkuneva$343.45
16GarrisonD'Amore$846.51
17LelahYundt$829.12
18KatlynnGerhold-Maggio$905.35
19CaraWyman$806.97
20JazlynGulgowski$79.36
21OmarQuitzon$927.59
22ElinoreBrown$839.25
23HenriMann$664.87
24EstebanMarvin$84.90
25RebecaBode$751.65
26LaurenSchroeder$138.41
27JordonDuBuque$467.99
28AlessandraRodriguez$717.76
29AnahiRunte-Marvin$472.91
30AnibalKautzer$102.63
31CaylaDibbert$788.19
32TobyKohler$417.29
33DejahSchowalter$502.22
34WillaAbshire$894.98
35BradHeaney-Schmeler$484.91
36MckennaWisoky$798.85
37DockZemlak$650.75
38AthenaNicolas$236.46
39GeorgianaMetz$281.23
40StefanSanford$293.15
41RyannKeeling-Swaniawski$45.89
42TyreseCasper$355.96
43AddieSwift$596.49
44DarrylGusikowski$363.57
45LondonKutch$418.63
46ClemmieHintz$3.53
47MinaSchulist$857.16
48MyrtisWehner$335.54
49EdythHansen$908.02
50WainoCarroll$882.28
"use client"; import { DataTable, DataTableBody } from "@optiaxiom/react"; import { getCoreRowModel, useReactTable } from "@tanstack/react-table"; import { columns } from "./columns"; import { data } from "./data"; export function App() { const table = useReactTable({ columns, data, getCoreRowModel: getCoreRowModel(), state: { pagination: { pageIndex: 0, pageSize: data.length } }, }); return ( <DataTable maxH="xs" table={table}> <DataTableBody /> </DataTable> ); }

#

Column pinning

Follow the column pinning guide  and use the columnPinning option to pin columns either to the left or right side of the table.

1Korbin.HettingerMegane34@gmail.comHelenaNicolasLegacy Directives Officer$696.47
2Lily68Itzel_Trantow@hotmail.comIlaMooreHuman Functionality Analyst$92.10
3Maxwell_Walsh35Marlon.Runolfsdottir@yahoo.comLucindaCreminLegacy Solutions Planner$510.42
4Elwin.SimonisHarley.Pouros39@hotmail.comMalvinaLueilwitzDirect Research Director$304.77
5Kristin45Cordie_Turcotte@gmail.comNewtonKeeblerCorporate Communications Facilitator$521.53
6Ollie82Claud_Haag@gmail.comHenriSchultzDistrict Accounts Planner$741.86
7Norberto65Isabelle46@gmail.comThereseBarrowsCustomer Implementation Developer$128.63
8Ignacio.Beahan9Maiya.Leannon@hotmail.comEssieVonInternal Directives Administrator$769.40
9Vilma.Bailey50Willa.Abshire@yahoo.comVestaRauNational Data Consultant$807.79
10Alma42Athena.Nicolas36@gmail.comCarlaArmstrongCustomer Response Orchestrator$993.04
11Jean_White50Rickie.Metz72@yahoo.comSerenaOkunevaNational Operations Planner$355.96
12Leopold88Hilda68@yahoo.comErvinWehnerNational Markets Producer$480.89
13Dawson46Beaulah_Bosco@yahoo.comCordeliaPowlowskiFuture Mobility Designer$709.63
14Drew.VandervortPaolo_Kovacek67@gmail.comTrinityErdmanCentral Functionality Coordinator$237.48
15Annamarie.Jacobi95Twila.Moore@gmail.comEdwinJast-O'ReillyChief Creative Director$444.22
16Joany23Sarah_VonRueden@hotmail.comRosaleeBaileyRegional Branding Representative$625.21
17Betty98Modesto.Zulauf64@gmail.comBillKleinInvestor Mobility Technician$134.61
18Jabari.Zemlak22Geoffrey.Trantow42@hotmail.comRayKiehnHuman Factors Specialist$919.48
19Johnson_Dare75Alfred_Beer37@gmail.comMarcusSchmelerFuture Operations Designer$147.72
20Rusty60Deondre_Rowe@gmail.comPatriciaKemmer-TorpCentral Division Specialist$817.10
21Darrin47Demarco.Jacobson@gmail.comAlexKossLead Quality Developer$715.75
22Merritt_Welch62Shea_Rolfson-Lindgren@gmail.comEnricoKoepp-PaucekCorporate Applications Engineer$31.66
23Keaton.BreitenbergFranco_Buckridge80@yahoo.comNelleMcGlynnInternal Directives Strategist$225.53
24Zoe29Ottis.Blick46@hotmail.comJaymeRyanDirect Implementation Engineer$328.33
25May_Gottlieb-Bernier69Zetta_Mertz66@yahoo.comAnastacioStokesInternational Implementation Supervisor$15.01
26Omari_McGlynnDandre_Runte@hotmail.comTalonGoyetteChief Interactions Producer$338.58
27Eugenia.Spencer41Clinton_OHara22@yahoo.comFelipeLangworthFuture Research Strategist$554.41
28Victoria.ErnserAshleigh.Hudson@yahoo.comTaraPollichGlobal Functionality Strategist$205.35
29Leonie.FisherDevyn.Reilly91@gmail.comFaustinoKunde-RolfsonInvestor Functionality Manager$83.34
30Josephine_Hickle32Victor87@yahoo.comRicoMorarLead Branding Technician$393.42
31Dakota72Jeff42@yahoo.comFavianHoppeDynamic Directives Executive$751.12
32Garland33Maryann_Powlowski@yahoo.comAlanisBatzGlobal Group Liaison$668.00
33Lynn.JohnsMiracle39@gmail.comBenedictFriesenDirect Accountability Architect$458.82
34Vella_BeerKatie_Lang@hotmail.comRessieHalvorsonProduct Applications Supervisor$497.47
35Issac_OConnellElody_Green49@yahoo.comLeahBernhardDirect Branding Director$264.40
36Terence0Janie.Dickinson17@yahoo.comAmosHackettChief Integration Liaison$447.36
37Zackery_Zemlak16Angela62@yahoo.comZeldaArmstrongGlobal Data Supervisor$356.24
38Brandy75Darrell.Marvin44@gmail.comAngusMarvinInternational Brand Designer$680.19
39Maya97Sallie.Crona@gmail.comMeggieBruenLegacy Directives Director$957.85
40Isai.BeahanMaximus.Schmidt@yahoo.comRethaSwaniawskiDirect Factors Executive$673.63
41Meredith86Ashleigh_Raynor29@gmail.comAshleighShanahanLead Response Officer$493.83
42Garrick71Merritt84@yahoo.comHassieSpencerCentral Factors Consultant$193.32
43Guido.Crist59Morris.Witting61@yahoo.comMyahQuitzonProduct Operations Officer$863.86
44Eden27Lilian.Collier@yahoo.comLoyalRau-SchowalterLegacy Infrastructure Supervisor$238.55
45Jonatan80Sadie.Huels86@gmail.comCathrynSchimmelInvestor Mobility Officer$347.06
46Leola_Block67Jensen_Leannon5@gmail.comDellDaughertyLead Data Facilitator$704.51
47Danial80Leatha95@yahoo.comDelaneyBergnaumDynamic Implementation Representative$828.99
48Archibald_Sipes92Seamus.Corkery54@gmail.comFabianBlickRegional Data Director$711.01
49Alonzo8Roel91@gmail.comEzekielCollierDistrict Marketing Analyst$937.37
50Louis75Jensen_Stamm53@hotmail.comJeannetteDooleyForward Web Developer$3.65
"use client"; import { DataTable, DataTableBody } from "@optiaxiom/react"; import { getCoreRowModel, useReactTable } from "@tanstack/react-table"; import { columns } from "./columns"; import { data } from "./data"; export function App() { const table = useReactTable({ columns, data, getCoreRowModel: getCoreRowModel(), state: { columnPinning: { left: ["id", "username"], }, pagination: { pageIndex: 0, pageSize: data.length }, }, }); return ( <DataTable maxH="xs" table={table}> <DataTableBody /> </DataTable> ); }

#

Row selection

Follow the row selection guide  to allow selecting and highlighting rows.

Use the DataTableCheckbox component to automatically attach selection handlers and make the whole row selectable.

Combine Checkbox/DataTableCheckbox with Cover to make them easier to interact with by spanning the whole cell.

Finally, make sure to use the DataTableLabel in your primary cell to set the label of the row and the checkbox for screen readers.

Check to select1
Krystel Kassulke MD
$696.47
Check to select2
Meredith Beier
$480.93
Check to select3
Mrs. Kelley Nicolas
$738.00
Check to select4
Dana Murray
$722.45
Check to select5
Itzel Kautzer DVM
$433.70
"use client"; import { DataTable, DataTableBody } from "@optiaxiom/react"; import { getCoreRowModel, useReactTable } from "@tanstack/react-table"; import { columns } from "./columns"; import { data } from "./data"; export function App() { const table = useReactTable({ columns, data, getCoreRowModel: getCoreRowModel(), }); return ( <DataTable table={table}> <DataTableBody /> </DataTable> ); }

#

Row actions

Use the DataTableAction component to show links, buttons, or dropdown menus within rows that are only visible when the user hovers over the row.

You can enable the primary prop on any one of those actions to mark that as the primary action. This will automatically enable keyboard navigation within the table:

  • Double click on row to perform primary action.
  • Use up/down/left/right arrow keys to navigate between rows and actions.

Finally, make sure to use the DataTableLabel in your primary cell to set the label of the row for screen readers.

Name
Nov 13, 2026
Krystel Kassulke MD
Nov 13, 2026
Miracle Daniel
Nov 13, 2026
Forest Greenholt
Nov 13, 2026
Shyanne Kuvalis
Nov 13, 2026
Mrs. Kayden Cartwright
"use client"; import { DataTable, DataTableBody } from "@optiaxiom/react"; import { getCoreRowModel, useReactTable } from "@tanstack/react-table"; import { columns } from "./columns"; import { data } from "./data"; export function App() { const table = useReactTable({ columns, data, enableRowSelection: false, getCoreRowModel: getCoreRowModel(), }); return ( <DataTable table={table}> <DataTableBody /> </DataTable> ); }

#

Pagination

DataTable supports both client-side and server-side pagination. Follow the pagination guide  to learn how to implement pagination with TanStack Table.

#

Client side

Simply provide the getPaginationRowModel and pagination options to use client-side pagination.

1KrystelWuckert$696.47
2FayeBeier$684.83
3CloydNicolas$398.04
4NathanFarrell$849.44
5HarveyKautzer$293.71
6TeaganBuckridge$312.26
7DestanyLeannon-Moore$317.28
8JohnnyJohnson$120.62
9MarcoPadberg$681.30
10DeliaBoyer$842.35

1 - 10 of 50

"use client"; import { DataTable, DataTableBody, DataTableFooter } from "@optiaxiom/react"; import { getCoreRowModel, getPaginationRowModel, useReactTable, } from "@tanstack/react-table"; import { columns } from "./columns"; import { data } from "./data"; export function App() { const table = useReactTable({ columns, data, getCoreRowModel: getCoreRowModel(), getPaginationRowModel: getPaginationRowModel(), initialState: { pagination: { pageIndex: 0, pageSize: 10 } }, }); return ( <DataTable maxH="xs" table={table}> <DataTableBody /> <DataTableFooter /> </DataTable> ); }

#

Server side

To implement manual server-side pagination we can use manualPagination and rowCount. Then combine it with onPaginationChange and state.pagination to control pagination and react to changes.

1KrystelWuckert$696.47
2FayeBeier$684.83
3CloydNicolas$398.04
4NathanFarrell$849.44
5HarveyKautzer$293.71
6TeaganBuckridge$312.26
7DestanyLeannon-Moore$317.28
8JohnnyJohnson$120.62
9MarcoPadberg$681.30
10DeliaBoyer$842.35

1 - 10 of 50

"use client"; import { DataTable, DataTableBody, DataTableFooter } from "@optiaxiom/react"; import { getCoreRowModel, useReactTable } from "@tanstack/react-table"; import { useMemo, useState } from "react"; import { columns } from "./columns"; import { data } from "./data"; /** * Simulate fetching data from server. */ const fetchData = ({ pageIndex = 0, pageSize = 10 }) => data.slice(pageIndex * pageSize, (pageIndex + 1) * pageSize); export function App() { const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10, }); const table = useReactTable({ columns, data: useMemo(() => fetchData(pagination), [pagination]), getCoreRowModel: getCoreRowModel(), manualPagination: true, onPaginationChange: setPagination, rowCount: data.length, state: { pagination }, }); return ( <DataTable maxH="xs" table={table}> <DataTableBody /> <DataTableFooter /> </DataTable> ); }

#

Loading state

Set the loading prop to true to show a loading skeleton while your table data is loading.

"use client"; import { DataTable, DataTableBody, Group, Switch } from "@optiaxiom/react"; import { getCoreRowModel, useReactTable } from "@tanstack/react-table"; import { useState } from "react"; import { columns } from "./columns"; export function App() { const [data] = useState([]); const table = useReactTable({ columns, data, getCoreRowModel: getCoreRowModel(), }); const [loading, setLoading] = useState(true); return ( <Group alignItems="start" flexDirection="column" gap="16" maxW="full"> <Switch checked={loading} onCheckedChange={setLoading}> Loading </Switch> <DataTable maxH="xs" table={table}> <DataTableBody loading={loading} /> </DataTable> </Group> ); }

Alternatively you can provide an object to the loading prop to denote individual loading state of sub rows.

1KrystelWuckert$696.47
2FayeBeier$684.83
3CloydNicolas$398.04
"use client"; import { DataTable, DataTableBody, Group, Switch } from "@optiaxiom/react"; import { getCoreRowModel, useReactTable } from "@tanstack/react-table"; import { useState } from "react"; import { columns } from "./columns"; import { data } from "./data"; export function App() { const table = useReactTable({ columns, data, getCoreRowModel: getCoreRowModel(), getRowId: (row) => row.id.toString(), }); const [loading, setLoading] = useState<Record<string, "sub-rows" | false>>({ "1": "sub-rows", }); return ( <Group alignItems="start" flexDirection="column" gap="16" maxW="full"> <Switch checked={loading["1"] === "sub-rows"} onCheckedChange={(checked) => setLoading({ "1": checked ? "sub-rows" : false }) } > Loading </Switch> <DataTable maxH="xs" table={table}> <DataTableBody loading={loading} /> </DataTable> </Group> ); }

#

Empty state

Use the empty prop on DataTableBody to show content in a full-width row when the table has no rows.

No payments yet.
"use client"; import { DataTable, DataTableBody } from "@optiaxiom/react"; import { getCoreRowModel, useReactTable } from "@tanstack/react-table"; import { columns } from "./columns"; export function App() { const table = useReactTable({ columns, data: [], getCoreRowModel: getCoreRowModel(), }); return ( <DataTable table={table}> <DataTableBody empty="No payments yet." /> </DataTable> ); }

#

Sorting

DataTable supports both client-side and server-side sorting. Follow the sorting guide  to learn how to implement sorting with TanStack Table.

#

Client side

Simply provide getSortedRowModel on table and optionally use enableSorting to control which columns you’d like to be sortable to use client-side sorting.

ID
1KrystelWuckert$696.47
2FayeBeier$684.83
3CloydNicolas$398.04
4NathanFarrell$849.44
5HarveyKautzer$293.71
6TeaganBuckridge$312.26
7DestanyLeannon-Moore$317.28
8JohnnyJohnson$120.62
9MarcoPadberg$681.30
10DeliaBoyer$842.35
"use client"; import { DataTable, DataTableBody } from "@optiaxiom/react"; import { getCoreRowModel, getSortedRowModel, useReactTable, } from "@tanstack/react-table"; import { columns } from "./columns"; import { data } from "./data"; export function App() { const table = useReactTable({ columns, data, getCoreRowModel: getCoreRowModel(), getSortedRowModel: getSortedRowModel(), }); return ( <DataTable maxH="xs" table={table}> <DataTableBody /> </DataTable> ); }

#

Server side

To implement manual server-side sorting we can use manualSorting. Then combine it with onSortingChange and state.sorting to control sorting and react to changes.

ID
3CloydNicolas$398.04
10DeliaBoyer$842.35
7DestanyLeannon-Moore$317.28
2FayeBeier$684.83
5HarveyKautzer$293.71
8JohnnyJohnson$120.62
1KrystelWuckert$696.47
9MarcoPadberg$681.30
4NathanFarrell$849.44
6TeaganBuckridge$312.26
"use client"; import { DataTable, DataTableBody } from "@optiaxiom/react"; import { getCoreRowModel, type SortingState, useReactTable, } from "@tanstack/react-table"; import { useMemo, useState } from "react"; import { columns } from "./columns"; import { data } from "./data"; export function App() { const [sorting, setSorting] = useState([ { desc: false, id: "firstName", }, ]); const table = useReactTable({ columns, data: useMemo(() => sortData(sorting), [sorting]), getCoreRowModel: getCoreRowModel(), onSortingChange: setSorting, state: { sorting }, }); return ( <DataTable maxH="xs" table={table}> <DataTableBody /> </DataTable> ); } /** * Simulate sorting data from server. */ const sortData = (sorting: SortingState) => data.toSorted((a, b) => { for (const state of sorting) { if ( !( state.id === "amount" || state.id === "firstName" || state.id === "lastName" ) ) { return 0; } const result = (state.desc ? -1 : 1) * a[state.id].localeCompare(b[state.id], undefined, { numeric: true }); if (result !== 0) { return result; } } return 0; });

#

List view

A collection page combines a search input and filter menus above the table with a primary create action. Wire search to globalFilter and each menu to its column’s filter value, add getFilteredRowModel and getPaginationRowModel, and TanStack resets to the first page whenever the criteria change. Put row commands in a trailing column behind one EllipsisMenuButton, and use empty to offer a way out when nothing matches.

Actions
Item 1
DraftAda Lovelace
Item 2
ReadyGrace Hopper
Item 3
ReadyAlan Turing
Item 4
DraftAda Lovelace
Item 5
ReadyGrace Hopper
Item 6
ReadyAlan Turing
Item 7
DraftAda Lovelace
Item 8
ReadyGrace Hopper
Item 9
ReadyAlan Turing
Item 10
DraftAda Lovelace

1 - 10 of 24

"use client"; import { IconPlus } from "@optiaxiom/icons"; import { Button, DataTable, DataTableBody, DataTableFooter, Flex, Group, LabelMenuButton, Menu, MenuContent, MenuTrigger, SearchInput, toaster, } from "@optiaxiom/react"; import { type ColumnFiltersState, getCoreRowModel, getFilteredRowModel, getPaginationRowModel, useReactTable, } from "@tanstack/react-table"; import { useRef, useState } from "react"; import { columns } from "./columns"; import { data } from "./data"; const filters = [ { id: "status", label: "Status", values: ["Draft", "Ready"] }, { id: "owner", label: "Owner", values: [...new Set(data.map((item) => item.owner))].sort(), }, ]; export function App() { const searchRef = useRef<HTMLInputElement>(null); const [globalFilter, setGlobalFilter] = useState(""); const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]); const table = useReactTable({ columns, data, getCoreRowModel: getCoreRowModel(), getFilteredRowModel: getFilteredRowModel(), getPaginationRowModel: getPaginationRowModel(), globalFilterFn: "includesString", initialState: { pagination: { pageIndex: 0, pageSize: 10 } }, onColumnFiltersChange: setColumnFilters, onGlobalFilterChange: setGlobalFilter, state: { columnFilters, globalFilter }, }); return ( <Flex maxW="full" w="full"> <Group flexWrap="wrap" gap="12" justifyContent="space-between"> <Group flexWrap="wrap" gap="8"> <SearchInput aria-label="Search items" onValueChange={setGlobalFilter} placeholder="Search items" ref={searchRef} size="lg" value={globalFilter} /> {filters.map((filter) => { const column = table.getColumn(filter.id); const value = column?.getFilterValue() as string | undefined; return ( <Menu key={filter.id} options={[undefined, ...filter.values].map((option) => ({ execute: () => column?.setFilterValue(option), label: option ?? "All", selected: value === option, }))} > <MenuTrigger asChild> <LabelMenuButton label={filter.label}> {value ?? "All"} </LabelMenuButton> </MenuTrigger> <MenuContent /> </Menu> ); })} </Group> <Button appearance="primary" icon={<IconPlus />} onClick={() => toaster.create("Create item")} size="lg" > Create item </Button> </Group> <DataTable table={table}> <DataTableBody empty={ <> No items match your filters. <Button appearance="subtle" mt="8" onClick={() => { setGlobalFilter(""); setColumnFilters([]); searchRef.current?.focus(); }} > Clear filters </Button> </> } /> <DataTableFooter /> </DataTable> </Flex> ); }

#

Expanding rows ALPHA

Follow the expanding guide  to allow expanding and collapsing rows.

Use the DataTableExpandableHeader and DataTableExpandableCell components to render columns with built-in buttons for toggling rows.

Finally, combine it with the loading prop to show a loading state while expanded rows are being fetched.

1
Clothing
$1415.94
2
Books
$919.50
"use client"; import { DataTable, DataTableBody } from "@optiaxiom/react"; import { getCoreRowModel, getExpandedRowModel, useReactTable, } from "@tanstack/react-table"; import { columns } from "./columns"; import { data } from "./data"; export function App() { const table = useReactTable({ columns, data, getCoreRowModel: getCoreRowModel(), getExpandedRowModel: getExpandedRowModel(), getSubRows: (row) => row.items, }); return ( <DataTable table={table}> <DataTableBody /> </DataTable> ); }

#

Virtualized

Table automatically uses virtualized rendering when rows and columns cross a certain threshold to improve rendering performance.

Columns will be virtualized when there are more than 20 columns in a table and rows will be virtualized when there are more than 20 rows rendered or if columns are also being virtualized.

Timer: 0s (to simulate re-rendering)

"use client"; import { faker } from "@faker-js/faker"; import { DataTable, DataTableBody, Group, Text } from "@optiaxiom/react"; import { getCoreRowModel, useReactTable } from "@tanstack/react-table"; import { useInViewTimer } from "./useInViewTimer"; faker.seed(123); const cols = 50; const rows = 500; const data = Array.from({ length: rows }, () => Object.fromEntries( Array.from({ length: cols }, (_, index) => [ `col${index}`, faker.book.title(), ]), ), ); const columns = Array.from({ length: cols }, (_, index) => ({ accessorKey: `col${index}`, header: `Column ${index + 1}`, })); export function App() { const table = useReactTable({ columns, data, getCoreRowModel: getCoreRowModel(), state: { pagination: { pageIndex: 0, pageSize: data.length } }, }); /** * A simple hook to re-render the table when it is visible on the screen. */ const [count, ref] = useInViewTimer(); return ( <Group flexDirection="column" gap="16" maxW="full" ref={ref}> <Text>Timer: {count}s (to simulate re-rendering)</Text> <DataTable maxH="sm" table={table}> <DataTableBody /> </DataTable> </Group> ); }

Table

Display tabular data using rows and columns.

Pagination

Display active page and navigate between multiple pages.

#

Props

#

DataTable

import { DataTable } from "@optiaxiom/react"; // or import { DataTable } from "@optiaxiom/react/data-table";

Supports all Box props in addition to its own. Renders a <div> element.

Prop

asChild

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

false | true

children

ReactNode

className

string

table*

Pass the table instance returned from useReactTable() hook.

Table<any>

#

DataTableBody

import { DataTableBody } from "@optiaxiom/react"; // or import { DataTableBody } from "@optiaxiom/react/data-table";

Supports all Box props in addition to its own. Renders a <div> element.

Prop

asChild

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

false | true

children

ReactNode

className

string

empty

Content to show in a full-width row when the table has no rows and isn’t loading.

ReactNode

estimatedRowHeight

The estimated height of rows in pixels when virtualization is enabled.

number

Default: 52

loading

Whether to show skeleton for the whole table or specific rows.

false | true | Record<string, false | "sub-rows">

#

DataTableFooter

import { DataTableFooter } from "@optiaxiom/react"; // or import { DataTableFooter } from "@optiaxiom/react/data-table";

Supports all Box props in addition to its own. Renders a <div> element.

Prop

asChild

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

false | true

children

ReactNode

className

string

pageSizeOptions

Specify a custom set of page size options.

{ label: string; value: string; }[]

Default: ["10", "20", "30", "50", "100"].map((size) => ({ label: size, value: size, }))

showPageSizeOptions

Whether to show a dropdown that allows controlling how many rows to show per page.

false | true

#

DataTableAction

import { DataTableAction } from "@optiaxiom/react"; // or import { DataTableAction } from "@optiaxiom/react/data-table";

Supports all Box props in addition to its own. Renders a <div> element.

Prop

asChild

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

false | true

children

ReactNode

className

string

primary

Whether this is the primary action within the row.

false | true

visible

Control whether to always show the contents or only when user is hovering or interacting with them.

"always" | "if-needed"

#

DataTableCheckbox

import { DataTableCheckbox } from "@optiaxiom/react"; // or import { DataTableCheckbox } from "@optiaxiom/react/data-table";

Supports all Box props in addition to its own. Renders a <div> element.

Prop

asChild

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

false | true

checked

Whether the input is checked. Use with onCheckedChange to control it.

false | true

children

ReactNode

className

string

defaultChecked

Whether the input is checked initially, when uncontrolled.

false | true

description

Add secondary text after the label.

ReactNode

disabled

Whether the input is disabled.

false | true

indeterminate

Display a partially checked icon instead of the regular checkmark.

false | true

name

The name of the form control element.

string

onCheckedChange

Handler that is called when the checked state changes.

(checked: boolean) => void

required

Whether selecting this input is required.

false | true

size

Control the size of the checkbox.

"sm" | "md"

value

The value of the form control element.

string | number | readonly string[]

visible

Control whether to always show the contents or only when user is hovering or interacting with them.

"always" | "if-needed"

#

DataTableLabel

import { DataTableLabel } from "@optiaxiom/react"; // or import { DataTableLabel } from "@optiaxiom/react/data-table";

Supports all Box props in addition to its own. Renders a <div> element.

Prop

asChild

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

false | true

children

ReactNode

className

string

#

Accessibility

#

Labels

  • Put DataTableLabel in each row’s primary cell. It names the row and its selection checkbox for screen readers.

#

Keyboard navigation

  • Mark one DataTableAction per row as primary to enable arrow key navigation between rows and actions.

#

Changelog

#

1.5.0

  • Added DataTableAction component
  • Added DataTableCheckbox component
  • Added DataTableLabel component

#

1.4.0

  • Moved component out of Alpha.

    // Before import { DataTable } from "@optiaxiom/react/unstable"; // After import { DataTable } from "@optiaxiom/react";

#

0.3.0

  • Added component
Last updated on