Skip to content

Latest commit

 

History

History
520 lines (388 loc) · 13.1 KB

HYBRID_TABLE_STRATEGY.md

File metadata and controls

520 lines (388 loc) · 13.1 KB

Hybrid Table Strategy: React Admin + TanStack Table

Date: October 2, 2025 Approach: Best of Both Worlds - Use the right tool for the right job


🎯 The Hybrid Approach

Core Philosophy

Don't replace what works - Keep React Admin datagrids for standard CRUD operations. Add TanStack Table - Use for advanced analytics, custom dashboards, and specialized views.


📋 When to Use Each

✅ Use React Admin Datagrids When:

Scenario Why React Admin Example
Standard CRUD Built-in edit/create/delete Contacts list page
Simple lists Quick implementation Companies directory
React Admin ecosystem Tight integration with ra-core All existing CRM views
Rapid prototyping Minimal code required Quick admin interfaces
Backend filters Built-in query integration Server-side filtering

Code Example:

// Existing Contacts List - KEEP AS IS
<Datagrid>
  <TextField source="name" />
  <EmailField source="email" />
  <EditButton />
</Datagrid>

✅ Use TanStack Table When:

Scenario Why TanStack Example
Analytics dashboards Full customization Revenue analytics widget
Complex filtering Advanced filter UI Multi-faceted search
Custom styling Theme integration Branded reports
Drag & drop Built-in with @dnd-kit Priority ranking
Virtual scrolling Performance Large datasets (10k+ rows)
Column resizing User-configurable Custom report views
Export features Full control CSV/PDF exports

Code Example:

// NEW Analytics Widget - Use TanStack
import { RecentDealsWidget } from '@/components/analytics/RecentDealsWidget';

<RecentDealsWidget />

🗺️ Application Mapping

Current CRM Views (Keep React Admin)

/contacts               → React Admin Datagrid ✅
/contacts/:id           → React Admin Edit Form ✅
/companies              → React Admin Datagrid ✅
/companies/:id          → React Admin Edit Form ✅
/deals                  → React Admin Kanban ✅
/deals/:id              → React Admin Edit Form ✅

Reason: These work perfectly, are stable, and users are familiar with them.


New Analytics Views (Use TanStack)

/dashboard/analytics    → TanStack Table 🆕
/reports/revenue        → TanStack Table 🆕
/reports/pipeline       → TanStack Table 🆕
/analytics/performance  → TanStack Table 🆕

Reason: Need custom styling, theme integration, and advanced features.


🏗️ Implementation Guide

Example 1: Dashboard Analytics Widget

Use Case: Show recent deals with custom theming

Implementation:

// src/atomic-crm/dashboard/Dashboard.tsx
import { RecentDealsWidget } from '@/components/analytics/RecentDealsWidget';

export const Dashboard = () => (
  <div className="space-y-6">
    {/* Existing dashboard stats */}
    <Welcome />
    <MonthlyRevenue />

    {/* NEW: TanStack Table widget */}
    <RecentDealsWidget />
  </div>
);

Features:

  • ✅ Sortable columns
  • ✅ Pagination
  • ✅ Theme-aware styling
  • ✅ Custom badge components
  • ✅ Currency formatting

Example 2: Advanced Filters Page

Use Case: Multi-criteria search with custom UI

// src/atomic-crm/reports/AdvancedSearch.tsx
import { useReactTable } from '@tanstack/react-table';
import { DataTable } from '@/components/data-table/data-table';
import { Input } from '@/components/ui/input';
import { Select } from '@/components/ui/select';

export const AdvancedSearch = () => {
  const [filters, setFilters] = useState({
    dateRange: [null, null],
    status: [],
    valueMin: 0,
    valueMax: 1000000,
  });

  const table = useReactTable({
    data: filteredData,
    columns: customColumns,
    // ... full control over filtering
  });

  return (
    <Card>
      <div className="filter-panel">
        {/* Custom filter UI */}
        <DateRangePicker value={filters.dateRange} />
        <MultiSelect value={filters.status} />
        <Slider min={0} max={1000000} />
      </div>

      <DataTable table={table} columns={customColumns} />
    </Card>
  );
};

📊 Feature Comparison

Feature React Admin TanStack Table
Edit inline ✅ Built-in ❌ Manual implementation
Delete rows ✅ Built-in ❌ Manual implementation
Create new ✅ Built-in ❌ Manual implementation
Backend integration ✅ Automatic ⚠️ Manual via React Query
Custom styling ⚠️ Limited ✅ Full control
Drag & drop ❌ No ✅ Yes (with dnd-kit)
Column resizing ❌ No ✅ Yes
Virtual scrolling ❌ No ✅ Yes (with plugin)
Theme integration ⚠️ Partial ✅ Perfect
Export data ⚠️ Basic ✅ Full control
Learning curve ⏱️ Low ⏱️ Medium

🎨 Theme Integration

TanStack Table with Theme Presets

TanStack tables automatically inherit your theme presets:

// Component uses shadcn/ui components which respect themes
<DataTable table={table} columns={columns} />

// When user selects "Tangerine" preset:
// → Table borders: orange
// → Primary actions: warm gold
// → Backgrounds: beige tones

// When user toggles Dark mode:
// → Same preset, dark variant

React Admin Datagrids: Harder to theme, require CSS overrides.


🔄 Migration Strategy (If Needed)

Phase 1 (Current): Hybrid Coexistence

  • Keep all existing React Admin views
  • Add TanStack for new features only
  • Status: ✅ Complete

Phase 2 (Optional): Selective Migration

  • Migrate 1-2 high-traffic pages (e.g., Contacts)
  • A/B test performance and UX
  • Timeline: Q1 2026 (if desired)

Phase 3 (Optional): Full Migration

  • Replace all React Admin datagrids
  • Rebuild edit/create forms
  • Timeline: TBD

Recommendation: Stay in Phase 1 unless specific needs arise.


💻 Code Examples

React Admin Datagrid (Keep)

// src/atomic-crm/contacts/ContactList.tsx
import { Datagrid, List, TextField, EmailField, EditButton } from 'react-admin';

export const ContactList = () => (
  <List>
    <Datagrid>
      <TextField source="first_name" />
      <TextField source="last_name" />
      <EmailField source="email" />
      <EditButton />
    </Datagrid>
  </List>
);

Pros: 5 lines of code, works perfectly. Keep it: ✅


TanStack Table (New Features)

// src/components/analytics/RecentDealsWidget.tsx
import { useReactTable } from '@tanstack/react-table';
import { DataTable } from '@/components/data-table/data-table';

export const RecentDealsWidget = () => {
  const table = useReactTable({
    data: deals,
    columns: customColumns,
    getCoreRowModel: getCoreRowModel(),
    getSortedRowModel: getSortedRowModel(),
  });

  return (
    <Card className="p-6">
      <h3>Recent Deals Analytics</h3>
      <DataTable table={table} columns={customColumns} />
      <DataTablePagination table={table} />
    </Card>
  );
};

Pros: Full customization, theme-aware, modern UI. Use for: NEW features only.


📚 Developer Guidelines

For New Features

Ask yourself:

  1. Is this a standard CRUD view? → Use React Admin (faster)

  2. Do I need custom styling or advanced features? → Use TanStack Table

  3. Is this a dashboard widget or analytics view? → Use TanStack Table

  4. Am I replacing an existing view? → Keep React Admin unless there's a strong reason to change


Component Location

src/
├── atomic-crm/
│   ├── contacts/          # React Admin views ✅
│   ├── companies/         # React Admin views ✅
│   ├── deals/             # React Admin views ✅
│   └── dashboard/         # Mix of both
│       ├── Welcome.tsx            # Existing
│       └── RecentDeals.tsx        # NEW: TanStack widget
├── components/
│   ├── data-table/        # TanStack Table components
│   └── analytics/         # Analytics widgets (TanStack)

🧪 Testing Checklist

Before Deploying TanStack Tables

  • Test with all 4 theme presets (Default, Tangerine, Brutalist, Soft Pop)
  • Test dark/light mode toggle
  • Verify sorting works
  • Verify pagination works
  • Test on mobile (responsive)
  • Check performance with 100+ rows
  • Verify export features (if implemented)
  • Test keyboard navigation (accessibility)

Verify React Admin Still Works

  • Open /contacts - datagrid loads
  • Edit a contact - form works
  • Open /companies - datagrid loads
  • Open /deals - kanban works
  • No console errors

🚀 Quick Start: Adding Your First TanStack Table

Step 1: Create Component

// src/components/analytics/YourWidget.tsx
import { useReactTable, getCoreRowModel } from '@tanstack/react-table';
import { DataTable } from '@/components/data-table/data-table';

export const YourWidget = () => {
  const data = [/* your data */];
  const columns = [/* your columns */];

  const table = useReactTable({
    data,
    columns,
    getCoreRowModel: getCoreRowModel(),
  });

  return <DataTable table={table} columns={columns} />;
};

Step 2: Add to Dashboard

// src/atomic-crm/dashboard/Dashboard.tsx
import { YourWidget } from '@/components/analytics/YourWidget';

<YourWidget />

Step 3: Test


📦 Available Components

TanStack Table Components

Component Path Purpose
<DataTable> @/components/data-table/data-table Main table
<DataTablePagination> @/components/data-table/data-table-pagination Pagination controls
<DataTableColumnHeader> @/components/data-table/data-table-column-header Sortable headers
<DataTableViewOptions> @/components/data-table/data-table-view-options Column visibility toggle
<DraggableRow> @/components/data-table/draggable-row Drag & drop rows

🎓 Learning Resources

TanStack Table Docs

Our Components

  • See: src/components/analytics/RecentDealsWidget.tsx for full example
  • See: src/components/data-table/ for component source

🔧 Troubleshooting

Issue: Table not themed correctly

Solution: Ensure you're using shadcn/ui components for cells:

// ❌ BAD
<td>{value}</td>

// ✅ GOOD
import { TableCell } from '@/components/ui/table';
<TableCell>{value}</TableCell>

Issue: Drag & drop not working

Solution: Ensure dnd-kit is installed and dndEnabled prop is true:

<DataTable table={table} columns={columns} dndEnabled={true} />

Issue: Performance slow with large datasets

Solution: Use pagination or virtual scrolling:

const table = useReactTable({
  // ...
  getPaginationRowModel: getPaginationRowModel(),
  initialState: {
    pagination: { pageSize: 50 },
  },
});

📊 Real-World Examples

Example 1: Recent Deals Analytics

Location: src/components/analytics/RecentDealsWidget.tsx Features: Sorting, pagination, custom badges, currency formatting Use Case: Dashboard widget showing pipeline activity

Example 2: Revenue Report (Future)

// Planned: src/components/analytics/RevenueReport.tsx
// Features:
// - Date range filtering
// - Group by month/quarter/year
// - Export to CSV
// - Charts integration

Example 3: Task Priority List (Future)

// Planned: src/components/analytics/TaskPriority.tsx
// Features:
// - Drag & drop reordering
// - Inline status updates
// - Deadline highlighting

✅ Best Practices

DO:

  • ✅ Use TanStack for NEW dashboards and analytics
  • ✅ Keep React Admin for CRUD operations
  • ✅ Test themes with both light and dark modes
  • ✅ Use shadcn/ui components for consistent theming
  • ✅ Implement pagination for large datasets
  • ✅ Use TypeScript for type safety

DON'T:

  • ❌ Replace working React Admin views without reason
  • ❌ Mix both in the same view (confusing UX)
  • ❌ Skip theme testing
  • ❌ Forget accessibility (keyboard nav, ARIA labels)
  • ❌ Build without pagination (performance issues)

🎯 Decision Flowchart

New Feature Request
       ↓
Is it CRUD (Create/Read/Update/Delete)?
       ↓ YES                          ↓ NO
Use React Admin              Is it analytics/dashboard?
       ✅                             ↓ YES
                              Use TanStack Table
                                     ✅

📈 Success Metrics

How We'll Know the Hybrid Approach is Working

  • ✅ No regressions in existing CRM features
  • ✅ Faster development for new analytics features
  • ✅ Consistent theming across all tables
  • ✅ Positive user feedback on new widgets
  • ✅ Maintainability remains high

Summary: Keep what works (React Admin), add what's better (TanStack) for new features. Win-win! 🎉

Questions? See example: src/components/analytics/RecentDealsWidget.tsx