@sproutsocial/seeds-react-data-table
v2.1.0
Published
Seeds React DataTable
Downloads
714
Readme
DataTable
A 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.
Installation
yarn add @sproutsocial/seeds-react-data-tableFeatures
- 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
- 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
Basic Usage
Simple String Columns
The easiest way to get started. Column names automatically map to data keys via camelCase conversion.
import { DataTable } from '@sproutsocial/seeds-react-data-table';
const data = [
{ name: 'John Doe', age: 28, occupation: 'Engineer' },
{ name: 'Jane Smith', age: 32, occupation: 'Designer' },
];
<DataTable
columns={['Name', 'Age', 'Occupation']}
data={data}
caption="Team Members"
/>Column Mapping Examples:
"Name"→name"First Name"→firstName"Email Address"→emailAddress
Advanced TanStack ColumnDef
For full control over rendering, sorting, and behavior:
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<Person>[] = [
{
accessorKey: 'name',
header: 'Full Name',
cell: (info) => <strong>{info.getValue()}</strong>,
},
{
accessorKey: 'email',
header: 'Email',
cell: (info) => (
<a href={`mailto:${info.getValue()}`}>{info.getValue()}</a>
),
},
{
accessorKey: 'active',
header: 'Status',
cell: (info) => (
<Badge>{info.getValue() ? 'Active' : 'Inactive'}</Badge>
),
},
];
<DataTable
columns={columns}
data={data}
caption="User Directory"
/>Custom Cell Rendering
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.
Basic Custom Cell Rendering
<DataTable
columns={['Name', 'Email', 'Status']}
data={data}
caption="Users"
renderCell={(info) => {
const value = info.getValue();
const columnId = info.column.id;
if (columnId === 'email') {
return <a href={`mailto:${value}`}>{value}</a>;
}
if (columnId === 'status') {
return <Badge>{value ? 'Active' : 'Inactive'}</Badge>;
}
return value;
}}
/>API-Driven Cell Rendering
Handle JSON responses with type information:
// API returns:
const apiData = [
{
name: 'John Doe',
email: { type: 'link', value: '[email protected]', href: 'mailto:[email protected]' },
status: { type: 'badge', value: 'Active', color: 'green' },
},
];
<DataTable
columns={['Name', 'Email', 'Status']}
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 <a href={cellData.href}>{cellData.value}</a>;
}
if (cellData.type === 'badge') {
return <Badge badgeColor={cellData.color}>{cellData.value}</Badge>;
}
}
return value;
}}
/>Conditional Cell Styling
Apply styling based on values:
<DataTable
columns={['Name', 'Score']}
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 (
<span style={{ color, fontWeight: 'bold' }}>
{score}/100
</span>
);
}
return value;
}}
/>Custom Caption Rendering
Use renderCaption to create complex table captions with badges, icons, and custom layouts.
Simple Caption
<DataTable
columns={['Name', 'Age']}
data={data}
caption="Team Members"
/>Caption with Badges
<DataTable
columns={['Name', 'Age']}
data={data}
caption={{
title: 'Team Members',
badges: [
{ text: 'Q1 2024' },
{ text: 'Active' },
],
}}
renderCaption={(captionData: any) => (
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
<span>{captionData.title}</span>
{captionData.badges?.map((badge: any, index: number) => (
<Badge key={index}>{badge.text}</Badge>
))}
</div>
)}
/>Caption with Icons
<DataTable
columns={['Name', 'Age']}
data={data}
caption={{
title: 'Post Performance',
badges: [
{ text: 'Jan 1 - Jan 31', iconName: 'calendar-outline' },
{ text: 'Social Media', iconName: 'tag-outline' },
],
}}
renderCaption={(captionData: any) => (
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
<span>{captionData.title}</span>
{captionData.badges?.map((badge: any, index: number) => (
<Badge key={index} iconName={badge.iconName}>
{badge.text}
</Badge>
))}
</div>
)}
/>Props
DataTableProps
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| columns | string[] | ColumnDef<TData>[] | 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 |
| 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 |
API-Driven Pattern
This component is designed to work seamlessly with API responses. Here's a complete example:
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<Record<string, unknown>>;
}
// Component Renderer
function ComponentRenderer({ apiResponse }: { apiResponse: APIResponse }) {
const renderCaption = (captionData: any) => (
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
<span>{captionData.title}</span>
{captionData.badges?.map((badge: any, index: number) => (
<Badge key={index} iconName={badge.iconName}>
{badge.text}
</Badge>
))}
</div>
);
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 <a href={cellData.href}>{cellData.value}</a>;
case 'badge':
return <Badge badgeColor={cellData.color}>{cellData.value}</Badge>;
case 'status':
return (
<Badge
iconName={cellData.active ? 'circle-check-solid' : 'circle-x-outline'}
badgeColor={cellData.active ? 'green' : 'red'}
>
{cellData.value}
</Badge>
);
default:
return cellData.value;
}
}
return value;
};
return (
<DataTable
columns={apiResponse.columns}
data={apiResponse.data}
caption={apiResponse.caption}
renderCaption={renderCaption}
renderCell={renderCell}
/>
);
}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:
const columns: ColumnDef<Person>[] = [
{
accessorKey: 'name',
header: 'Name',
enableSorting: false, // Disable sorting for this column
},
];Empty State
Display a custom message when no data is available:
<DataTable
columns={['Name', 'Age']}
data={[]}
caption="Users"
emptyMessage="No users found. Try adjusting your filters."
/>TypeScript
The component is fully typed with generics:
interface User {
id: string;
name: string;
email: string;
}
// Type is inferred from data
<DataTable<User>
columns={['Name', 'Email']}
data={users}
caption="Users"
/>Accessibility
- 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
When to Use
Use DataTable when:
- You need sorting functionality
- You want automatic camelCase column mapping
- You need custom cell rendering based on API data
- You require type-safe column definitions
- Dataset is < 100 rows
Use TableV2 instead when:
- You have simple string/ReactNode arrays
- You don't need sorting
- You want maximum simplicity
Use DataTableVirtualized instead when:
- Dataset is > 100 rows
- Performance is critical
- You need smooth scrolling with large data
Related Components
- TableV2: Simple tables with string/ReactNode arrays
- DataTableVirtualized: Virtualized tables for large datasets (> 100 rows)
Examples
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
