Data Table
Data table components are the organizers of information. They transform raw data into beautiful, sortable, and interactive tables with professional styling and seamless user experience.
Preview
Code
Name | Email | Role | Status |
|---|---|---|---|
| John Doe | john@example.com | Admin | Active |
| Jane Smith | jane@example.com | User | Active |
| Bob Johnson | bob@example.com | User | Inactive |
Installation
First, make sure you have the required dependencies:
npx @rajdevxd/aura-ui add data-table
yarn @rajdevxd/aura-ui add data-table
pnpm dlx @rajdevxd/aura-ui add data-table
bunx --bun @rajdevxd/aura-ui add data-table
Usage
Data table components provide sortable, interactive data display:
import { DataTable } from "@/components/ui/data-table"
interface Product {
id: number
name: string
price: number
category: string
inStock: boolean
}
const products: Product[] = [
{ id: 1, name: 'Laptop', price: 999, category: 'Electronics', inStock: true },
{ id: 2, name: 'Book', price: 29, category: 'Education', inStock: false },
// ... more products
]
const columns = [
{ key: 'name' as keyof Product, header: 'Product Name', sortable: true },
{ key: 'price' as keyof Product, header: 'Price', sortable: true },
{
key: 'category' as keyof Product,
header: 'Category',
render: (value: string) => <span className="capitalize">{value}</span>
},
{
key: 'inStock' as keyof Product,
header: 'Status',
render: (value: boolean) => (
<span className={`px-2 py-1 rounded-full text-xs ${
value ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'
}`}>
{value ? 'In Stock' : 'Out of Stock'}
</span>
)
}
]
const ProductTable = () => {
return (
<DataTable
data={products}
columns={columns}
onSort={(key, direction) => {
// Handle sorting logic
console.log(`Sorting by ${key} ${direction}`)
}}
/>
)
}Props
| Prop | Type | Required | Description |
|---|---|---|---|
data | T[] | Yes | Array of data objects |
columns | Column<T>[] | Yes | Column configuration array |
onSort | (key: keyof T, direction: 'asc' | 'desc') => void | No | Sort callback function |
className | string | No | Additional CSS classes |
emptyMessage | string | No | Message when no data |
Column Configuration
interface Column<T> {
key: keyof T // Data key to display
header: string // Column header text
sortable?: boolean // Enable sorting for this column
render?: (value: any, item: T) => React.ReactNode // Custom render function
className?: string // Additional column classes
}Features
- Column Sorting: Click headers to sort data
- Custom Rendering: Flexible cell content with render functions
- Responsive Design: Adapts to different screen sizes
- Empty States: Customizable no-data message
- TypeScript Support: Full type safety
- Accessible: Keyboard navigation and screen reader support
- Customizable: Extensive styling options
Advanced Usage
With Pagination
const PaginatedTable = () => {
const [currentPage, setCurrentPage] = useState(1)
const [sortKey, setSortKey] = useState<keyof Product | null>(null)
const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('asc')
const itemsPerPage = 10
const startIndex = (currentPage - 1) * itemsPerPage
const endIndex = startIndex + itemsPerPage
const handleSort = (key: keyof Product, direction: 'asc' | 'desc') => {
setSortKey(key)
setSortDirection(direction)
// Sort your data here
}
const paginatedData = sortedData.slice(startIndex, endIndex)
return (
<div className="space-y-4">
<DataTable
data={paginatedData}
columns={columns}
onSort={handleSort}
/>
<div className="flex justify-between items-center">
<span className="text-sm text-muted-foreground">
Showing {startIndex + 1} to {Math.min(endIndex, sortedData.length)} of {sortedData.length} entries
</span>
<div className="flex space-x-2">
<button
onClick={() => setCurrentPage(prev => Math.max(1, prev - 1))}
disabled={currentPage === 1}
className="px-3 py-1 border rounded disabled:opacity-50"
>
Previous
</button>
<span className="px-3 py-1">Page {currentPage}</span>
<button
onClick={() => setCurrentPage(prev => prev + 1)}
disabled={endIndex >= sortedData.length}
className="px-3 py-1 border rounded disabled:opacity-50"
>
Next
</button>
</div>
</div>
</div>
)
}With Actions
const TableWithActions = () => {
const handleEdit = (item: Product) => {
// Edit logic
}
const handleDelete = (item: Product) => {
// Delete logic
}
const actionColumns = [
...columns,
{
key: 'actions' as keyof Product,
header: 'Actions',
render: (_: any, item: Product) => (
<div className="flex space-x-2">
<button
onClick={() => handleEdit(item)}
className="px-2 py-1 text-blue-600 hover:bg-blue-50 rounded"
>
Edit
</button>
<button
onClick={() => handleDelete(item)}
className="px-2 py-1 text-red-600 hover:bg-red-50 rounded"
>
Delete
</button>
</div>
)
}
]
return (
<DataTable
data={products}
columns={actionColumns}
/>
)
}With Filtering
const FilterableTable = () => {
const [filter, setFilter] = useState('')
const [categoryFilter, setCategoryFilter] = useState('')
const filteredData = products.filter(product => {
const matchesSearch = product.name.toLowerCase().includes(filter.toLowerCase())
const matchesCategory = !categoryFilter || product.category === categoryFilter
return matchesSearch && matchesCategory
})
return (
<div className="space-y-4">
<div className="flex space-x-4">
<input
type="text"
placeholder="Search products..."
value={filter}
onChange={(e) => setFilter(e.target.value)}
className="px-3 py-2 border rounded"
/>
<select
value={categoryFilter}
onChange={(e) => setCategoryFilter(e.target.value)}
className="px-3 py-2 border rounded"
>
<option value="">All Categories</option>
<option value="Electronics">Electronics</option>
<option value="Books">Books</option>
<option value="Clothing">Clothing</option>
</select>
</div>
<DataTable
data={filteredData}
columns={columns}
emptyMessage="No products match your filters"
/>
</div>
)
}Common Patterns
User Management Table
const userColumns = [
{ key: 'name', header: 'Name', sortable: true },
{ key: 'email', header: 'Email', sortable: true },
{
key: 'role',
header: 'Role',
render: (value: string) => (
<span className={`px-2 py-1 rounded text-xs ${
value === 'Admin' ? 'bg-purple-100 text-purple-800' :
value === 'Editor' ? 'bg-blue-100 text-blue-800' :
'bg-gray-100 text-gray-800'
}`}>
{value}
</span>
)
},
{
key: 'status',
header: 'Status',
render: (value: string) => (
<span className={`px-2 py-1 rounded-full text-xs ${
value === 'Active' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'
}`}>
{value}
</span>
)
}
]Financial Data Table
const financialColumns = [
{ key: 'date', header: 'Date', sortable: true },
{ key: 'description', header: 'Description' },
{
key: 'amount',
header: 'Amount',
sortable: true,
render: (value: number) => (
<span className={value >= 0 ? 'text-green-600' : 'text-red-600'}>
${Math.abs(value).toFixed(2)}
</span>
)
},
{ key: 'category', header: 'Category' }
]Product Catalog
const productColumns = [
{
key: 'image',
header: 'Image',
render: (value: string) => (
<img src={value} alt="Product" className="w-12 h-12 object-cover rounded" />
)
},
{ key: 'name', header: 'Product Name', sortable: true },
{
key: 'price',
header: 'Price',
sortable: true,
render: (value: number) => `$${value.toFixed(2)}`
},
{
key: 'rating',
header: 'Rating',
render: (value: number) => '⭐'.repeat(Math.floor(value))
}
]Performance Considerations
Large Datasets
const OptimizedTable = () => {
// Use React.memo for expensive render functions
const memoizedColumns = useMemo(() => columns, [])
// Implement virtual scrolling for very large datasets
// Consider pagination for better performance
return (
<DataTable
data={largeDataset}
columns={memoizedColumns}
/>
)
}Sorting Optimization
const useSortedData = (data: T[], sortKey: keyof T | null, direction: 'asc' | 'desc') => {
return useMemo(() => {
if (!sortKey) return data
return [...data].sort((a, b) => {
const aValue = a[sortKey]
const bValue = b[sortKey]
if (aValue < bValue) return direction === 'asc' ? -1 : 1
if (aValue > bValue) return direction === 'asc' ? 1 : -1
return 0
})
}, [data, sortKey, direction])
}Contributing
Data table components organize the digital chaos! Help us improve their sorting algorithms, add more customization options, and enhance their performance with large datasets.
Data Table - because data deserves beautiful presentation! 📊✨