Seeds React DataTable
npm install @sproutsocial/seeds-react-data-tableA flexible, accessible data table component built with TanStack Table. Designed for displaying structured data with support for sorting, custom rendering, and both simple and advanced use cases.
``bash`
yarn add @sproutsocial/seeds-react-data-table
- Simple String Columns: Quick setup with automatic camelCase key mapping
- TanStack Table Integration: Full control with ColumnDef for advanced features
- Sorting: Built-in column sorting functionality
- Search/Filtering: Fuzzy search across all columns with TanStack Table
- Pagination: Simple show more/less pagination support
- Custom Cell Rendering: Flexible cell rendering for API-driven UIs
- Custom Caption Rendering: Support for complex table captions with badges and icons
- Accessible: Required captions for screen readers
- TypeScript Support: Full type safety with generics
The easiest way to get started. Column names automatically map to data keys via camelCase conversion.
`tsx
import { DataTable } from '@sproutsocial/seeds-react-data-table';
const data = [
{ name: 'John Doe', age: 28, occupation: 'Engineer' },
{ name: 'Jane Smith', age: 32, occupation: 'Designer' },
];
data={data}
caption="Team Members"
/>
`
Column Mapping Examples:
- "Name" → name"First Name"
- → firstName"Email Address"
- → emailAddress
For full control over rendering, sorting, and behavior:
`tsx
import { DataTable } from '@sproutsocial/seeds-react-data-table';
import type { ColumnDef } from '@tanstack/react-table';
interface Person {
name: string;
email: string;
active: boolean;
}
const columns: ColumnDef
{
accessorKey: 'name',
header: 'Full Name',
cell: (info) => {info.getValue()},
},
{
accessorKey: 'email',
header: 'Email',
cell: (info) => (
mailto:${info.getValue()}}>{info.getValue()}
),
},
{
accessorKey: 'active',
header: 'Status',
cell: (info) => (
),
},
];
data={data}
caption="User Directory"
/>
`
Use renderCell to customize how all cells are rendered when using string columns. Perfect for API-driven UIs where you want to apply consistent rendering logic.
`tsx
data={data}
caption="Users"
renderCell={(info) => {
const value = info.getValue();
const columnId = info.column.id;
if (columnId === 'email') {
return mailto:${value}}>{value};
}
if (columnId === 'status') {
return
}
return value;
}}
/>
`
Handle JSON responses with type information:
`tsx
// API returns:
const apiData = [
{
name: 'John Doe',
email: { type: 'link', value: 'john@example.com', href: 'mailto:john@example.com' },
status: { type: 'badge', value: 'Active', color: 'green' },
},
];
data={apiData}
caption="Users"
renderCell={(info) => {
const value = info.getValue();
// Handle objects with type hints
if (typeof value === 'object' && value !== null && 'type' in value) {
const cellData = value as any;
if (cellData.type === 'link') {
return {cellData.value};
}
if (cellData.type === 'badge') {
return
}
}
return value;
}}
/>
`
Apply styling based on values:
`tsx
data={data}
caption="Performance Scores"
renderCell={(info) => {
const value = info.getValue();
const columnId = info.column.id;
if (columnId === 'score') {
const score = value as number;
const color = score >= 90 ? 'green' : score >= 80 ? 'orange' : 'red';
return (
{score}/100
);
}
return value;
}}
/>
`
Use renderCaption to create complex table captions with badges, icons, and custom layouts.
`tsx`
data={data}
caption="Team Members"
/>
`tsx`
data={data}
caption={{
title: 'Team Members',
badges: [
{ text: 'Q1 2024' },
{ text: 'Active' },
],
}}
renderCaption={(captionData: any) => (
{captionData.title}
{captionData.badges?.map((badge: any, index: number) => (
))}
)}
/>
`tsx`
data={data}
caption={{
title: 'Post Performance',
badges: [
{ text: 'Jan 1 - Jan 31', iconName: 'calendar-outline' },
{ text: 'Social Media', iconName: 'tag-outline' },
],
}}
renderCaption={(captionData: any) => (
{captionData.title}
{captionData.badges?.map((badge: any, index: number) => (
{badge.text}
))}
)}
/>
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| columns | string[] \| ColumnDef | Yes | - | Column definitions. Either string array or TanStack ColumnDef array |data
| | TData[] | Yes | - | Array of data objects to display |caption
| | unknown | Yes | - | Table caption for accessibility. Can be any type when used with renderCaption |displayCaption
| | boolean | No | true | Whether to visually display the caption |emptyMessage
| | React.ReactNode | No | "No results" | Message to display when data array is empty |search
| | string | No | - | Search string for filtering table data. Uses fuzzy filtering across all columns |simplePaginationConfig
| | SimplePaginationConfig | No | - | Configuration for simple show more/less pagination |paginationConfig
| | PaginationConfig | No | - | Configuration for complex pagination with page navigation and size selection |renderCell
| | (info: CellContext) => React.ReactNode | No | - | Custom cell renderer for string columns. Receives TanStack Table cell context |renderCaption
| | (caption: unknown) => React.ReactNode | No | - | Custom caption renderer. Converts caption data to React elements |
This component is designed to work seamlessly with API responses. Here's a complete example:
`tsx
import { DataTable } from '@sproutsocial/seeds-react-data-table';
import { Badge } from '@sproutsocial/seeds-react-badge';
// API Response Structure
interface APIResponse {
caption: {
title: string;
badges: Array<{ text: string; iconName?: string }>;
};
columns: string[];
data: Array
}
// Component Renderer
function ComponentRenderer({ apiResponse }: { apiResponse: APIResponse }) {
const renderCaption = (captionData: any) => (
const renderCell = (info: any) => {
const value = info.getValue();
// Handle typed cells from API
if (typeof value === 'object' && value !== null && 'type' in value) {
const cellData = value as any;
switch (cellData.type) {
case 'link':
return {cellData.value};
case 'badge':
return
case 'status':
return (
badgeColor={cellData.active ? 'green' : 'red'}
>
{cellData.value}
);
default:
return cellData.value;
}
}
return value;
};
return (
data={apiResponse.data}
caption={apiResponse.caption}
renderCaption={renderCaption}
renderCell={renderCell}
/>
);
}
`
DataTable supports fuzzy filtering across all columns using TanStack Table's built-in filtering. Simply pass a search string to filter the data:
`tsx
import { DataTable } from '@sproutsocial/seeds-react-data-table';
import { useState } from 'react';
function SearchableTable() {
const [searchText, setSearchText] = useState('');
const data = [
{ name: 'John Doe', email: 'john@example.com', department: 'Engineering' },
{ name: 'Jane Smith', email: 'jane@example.com', department: 'Design' },
{ name: 'Bob Johnson', email: 'bob@example.com', department: 'Engineering' },
];
return (
$3
- Fuzzy Matching: Finds approximate matches, not just exact ones
- Case Insensitive: Searches ignore letter case
- Multi-Column: Searches across all columns automatically
- Pagination Reset: Automatically resets to page 1 when search changes
$3
Search works seamlessly with pagination - filtered results are paginated automatically:
`tsx
columns={['Name', 'Email', 'Department']}
data={largeDataset}
caption="User Directory"
search={searchText}
simplePaginationConfig={{
initialVisibleRows: 10,
expandBy: 10,
showMoreText: 'Show More',
showLessText: 'Show Less',
showAllText: 'Show All',
}}
/>
`Sorting
All columns support sorting by default. Click column headers to sort:
- First click: Sort ascending
- Second click: Sort descending
- Third click: Remove sort
To disable sorting for specific columns when using TanStack ColumnDef:
`tsx
const columns: ColumnDef[] = [
{
accessorKey: 'name',
header: 'Name',
enableSorting: false, // Disable sorting for this column
},
];
`Empty State
Display a custom message when no data is available:
`tsx
columns={['Name', 'Age']}
data={[]}
caption="Users"
emptyMessage="No users found. Try adjusting your filters."
/>
`TypeScript
The component is fully typed with generics:
`tsx
interface User {
id: string;
name: string;
email: string;
}// Type is inferred from data
columns={['Name', 'Email']}
data={users}
caption="Users"
/>
``- Required Caption: All tables must have a caption for screen readers
- Keyboard Navigation: Full keyboard support for sorting
- ARIA Labels: Proper ARIA attributes for table structure
- Screen Reader Support: Sort state announced to screen readers
- TableV2: Simple tables with string/ReactNode arrays
- DataTableVirtualized: Virtualized tables for large datasets (> 100 rows)
Check out the Storybook examples for more patterns:
- Simple string columns
- Advanced TanStack columns
- Custom cell rendering
- API-driven rendering
- Caption with badges
- Color-coded cells
- Empty states