DataTable
An advanced React table that supports filtering, sorting, and pagination out of the box.1<DataTableDemo />
Usage
1import {2 DataTable,3 DataTableColumnDef,4 DataTableQuery,5 DataTableSort,6 useDataTable,7 EmptyFilterValue8} from "@raystack/apsara";
DataTable Props
Prop
Type
DataTable.DisplayControls Props
Prop
Type
DataTable.Filters Props
Prop
Type
DataTableQuery Interface
Prop
Type
DataTableColumn Interface
Prop
Type
DataTable.Content Props
Prop
Type
Examples
Basic Usage
1import { DataTable } from "@raystack/apsara";23const columns = [4 {5 accessorKey: "name",6 header: "Name",7 columnType: "text",8 enableSorting: true,9 },10 {11 accessorKey: "age",12 header: "Age",13 columnType: "number",14 enableSorting: true,15 },16];17const data = [18 { name: "John Doe", age: 30 },19 { name: "Jane Smith", age: 25 },20];21function MyTable() {22 return (23 <DataTable24 columns={columns}25 data={data}26 defaultSort={{ key: "name", order: "asc" }}>27 <DataTable.Toolbar />28 <DataTable.Content />29 </DataTable>30 );31}
Column Configuration
Columns can be configured with various options:
1interface DataTableColumnDef<TData, TValue> {2 accessorKey: string; // Key to access data3 header: string; // Column header text4 columnType: "text" | "number" | "date" | "select"; // Data type5 enableSorting?: boolean; // Enable sorting6 enableColumnFilter?: boolean; // Enable filtering7 enableHiding?: boolean; // Enable column visibility toggle8 enableGrouping?: boolean; // Enable grouping9 filterOptions?: FilterSelectOption[]; // Options for select filter10 defaultHidden?: boolean; // Hide column by default11}
Filtering
The DataTable supports multiple filter types:
Filter types:
- Text: equals, not equals, contains,
- Number: equals, not equals, less than, less than or equal, greater than, greater than or equal
- Date: equals, not equals, before, on or before, after, on or after
- Select: equals, not equals
Sorting
Enable column sorting:
1const columns = [2 {3 accessorKey: "name",4 header: "Name",5 enableSorting: true,6 },7];
Grouping
Group rows by same column data:
1const columns = [2 {3 accessorKey: "category",4 header: "Category",5 enableGrouping: true,6 showGroupCount: true,7 },8];
Server-side Integration
1function ServerTable() {2 const [data, setData] = useState([]);3 const [query, setQuery] = useState();4 const [isLoading, setIsLoading] = useState(false);5 const handleQueryChange = async (query: DataTableQuery) => {6 setIsLoading(true);7 setQuery(query);8 const response = await fetchData(query);9 setData(response.data);10 setIsLoading(false);11 };12 return (13 <DataTable14 data={data}15 query={query}16 columns={columns}17 isLoading={isLoading}18 mode="server"19 onTableQueryChange={handleQueryChange}>20 <DataTable.Toolbar />21 <DataTable.Content />22 </DataTable>23 );24}
Custom Styling
1const columns = [2 {3 accessorKey: "name",4 header: "Name",5 classNames: {6 cell: "custom-cell",7 header: "custom-header",8 },9 styles: {10 cell: { fontWeight: "bold" },11 header: { backgroundColor: "#f5f5f5" },12 },13 },14];
Custom Cell Rendering
1const columns = [2 {3 accessorKey: "status",4 header: "Status",5 cell: ({ row }) => (6 <Badge status={row.original.status}>{row.original.status}</Badge>7 ),8 },9];
Using DataTable Filter
The DataTable.Filters component can be used separately to filter data for custom views.
1<DataTable2data={data}3query={query}4columns={columns}5mode="server"6onTableQueryChange={handleQueryChange}>7 <DataTable.Filters />8</DataTable>
Using DataTable Display Controls
The DataTable.DisplayControls component can be used separately to display the display controls for custom views.
1<DataTable2data={data}3query={query}4columns={columns}5mode="server"6onTableQueryChange={handleQueryChange}7onColumnVisibilityChange={handleColumnVisibilityChange}>8 <DataTable.DisplayControls />9</DataTable>
Using DataTable Search
The DataTable.Search component provides search functionality that automatically integrates with the table query. By default, it is disabled in zero state (when no data and no filters/search applied).
1<DataTable2 data={data}3 columns={columns}4 defaultSort={{ name: "name", order: "asc" }}>5 <DataTable.Search />6 <DataTable.Content />7</DataTable>
Search Auto-Disable Behavior
By default, DataTable.Search is automatically disabled in zero state to provide a better user experience. You can override this behavior:
1// Default: disabled in zero state2<DataTable.Search />34// Override: always enabled5<DataTable.Search autoDisableInZeroState={false} />67// Manual control: explicitly disable8<DataTable.Search disabled={true} />
The search will be automatically enabled when:
- Data exists in the table
- Filters are applied
- A search query is already present
Empty States
The DataTable supports two types of empty states to provide better user experience:
Zero State
Zero state is shown when no data has been fetched initially (no filters or search applied). In this state, the filter bar is automatically hidden.
1import { DataTable, EmptyState } from "@raystack/apsara";2import { OrganizationIcon } from "@raystack/apsara/icons";34<DataTable5 data={[]}6 columns={columns}7 defaultSort={{ name: "name", order: "asc" }}>8 <DataTable.Toolbar />9 <DataTable.Content10 zeroState={11 <EmptyState12 icon={<OrganizationIcon />}13 heading="No users yet"14 subHeading="Get started by creating your first user."15 />16 }17 />18</DataTable>
Empty State
Empty state is shown when initial data exists but no results match after applying filters or search. In this state, the filter bar remains visible so users can adjust their filters.
1import { DataTable, EmptyState } from "@raystack/apsara";2import { OrganizationIcon, FilterIcon } from "@raystack/apsara/icons";34<DataTable5 data={initialData}6 columns={columns}7 defaultSort={{ name: "name", order: "asc" }}>8 <DataTable.Toolbar />9 <DataTable.Search />10 <DataTable.Content11 zeroState={12 <EmptyState13 icon={<OrganizationIcon />}14 heading="No users yet"15 subHeading="Get started by creating your first user."16 />17 }18 emptyState={19 <EmptyState20 icon={<FilterIcon />}21 heading="No users found"22 subHeading="We couldn't find any matches for that keyword or filter. Try alternative terms or check for typos."23 />24 }25 />26</DataTable>
Fallback Behavior
- If
zeroStateis not provided, it falls back toemptyState - If neither
zeroStatenoremptyStateis provided, a default empty state is shown - The filter bar visibility is automatically controlled based on the state
Custom Empty State Content
You can provide custom React components for both states:
1import { DataTable, EmptyState, Flex, Text, Button } from "@raystack/apsara";2import { OrganizationIcon, FilterIcon } from "@raystack/apsara/icons";34<DataTable.Content5 zeroState={6 <Flex direction="column" gap={4} align="center" style={{ padding: "40px" }}>7 <OrganizationIcon width={48} height={48} style={{ opacity: 0.5 }} />8 <Flex direction="column" gap={2} align="center">9 <Text size={4} weight="medium">10 No data available11 </Text>12 <Text size={2} style={{ color: "var(--rs-color-text-subtle)" }}>13 There are no users in the system. Create your first user to get started.14 </Text>15 </Flex>16 <Button size="small">Create User</Button>17 </Flex>18 }19 emptyState={20 <EmptyState21 icon={<FilterIcon />}22 heading="No matches found"23 subHeading="Try adjusting your filters or search query."24 />25 }26/>