tnks-data-table

repository·main·Indexed 42 days ago

https://github.com/jacksonkasi1/tnks-data-table

A highly configurable, enterprise-grade data table component built on Shadcn UI and TanStack Table v8. It supports server-side pagination, sorting, and filtering, hierarchical subrows, row selection, and data export to CSV/Excel. Integrated with React Query for data fetching and Zod for schema validation, it is designed for Next.js 13+ applications requiring complex UI features like column resizing and bulk actions.

Tokens
43.2K
Snippets
116
Records
150
Agent score
53%

What's inside tnks-data-table

  1. Overview of Data Table features

    main

    The Advanced Data Table is a feature-rich implementation built on Shadcn UI and TanStack Table (React Table v8). It is framework-agnostic (compatible with Next.js, Vite, Remix, etc.) and supports enterprise-level requirements.

    Key Capabilities

    Data Management

    • Server-side pagination, sorting, and filtering.
    • Single and multi-row selection.
    • Hierarchical data with subrows (expandable nested rows).
    • Cross-page subrow selection and export.
    • Row click callbacks for navigation.
    • Optimistic UI updates.

    UI & Operations

    • Column resizing and visibility toggling.
    • Date range filtering and search functionality.
    • Data export (CSV/Excel) with custom formatting and transformations.
    • Bulk actions (e.g., bulk delete).
    • Responsive design and accessibility (WCAG compliant).
    • URL state persistence.
    • Case format conversion (e.g., snake_case ↔ camelCase).
  2. Overview of the Advanced Data Table Component

    main
    The Advanced Data Table is a highly configurable, enterprise-grade table implementation built on top of Shadcn UI and TanStack Table (React Table v8). It is designed to handle complex data operations, server-side processing, and customizable UI elements while maintaining accessibility (WCAG) and performance.
  3. How URL State Management works in the Data Table

    main

    The data table uses a custom useUrlState hook built on Next.js App Router's search params utilities to persist table state (pagination, sorting, filtering, etc.) directly in the URL.

    This approach provides:

    • Shareable URLs: Users can share links that preserve their exact view.
    • Browser history support: Forward/back navigation works with table state changes.
    • Bookmarkable states: Specific filtered views can be bookmarked.
    • SEO benefits: Search engines can index specific data views.
    • Type safety: Full TypeScript support via generics.

    When state changes, the hook updates the URL; when the URL changes (e.g., via browser navigation), the hook updates the local state.

    // Basic usage pattern
    const [page, setPage] = useUrlState("page", 1);
    const [dateRange, setDateRange] = useUrlState<{ from_date: string; to_date: string }>( 
      "dateRange", 
      { from_date: "", to_date: "" }
    );
  4. How subrows work with TanStack Table

    main

    The subrows feature is built on top of TanStack Table integration. It utilizes:

    • getExpandedRowModel(): To manage the expand/collapse state and visibility of nested rows.
    • getSubRows: To access the nested data structure within the table state.

    This integration ensures that standard table features like sorting, filtering, pagination, and column resizing continue to work seamlessly with hierarchical data.

  5. Understand the three DataTable rendering modes

    main

    The tnks-data-table supports three distinct rendering modes for displaying hierarchical or related data:

    1. Same-Columns Mode: Used when subrows share the same schema/columns as the parent rows (e.g., displaying order items within an orders table).
    2. Custom-Columns Mode: Used when subrows have a different structure or require specific columns that differ from the parent (e.g., displaying booking stops within a bookings table).
    3. Custom-Component Mode: Used when subrows require specialized UI components for rendering (e.g., displaying comments within a tickets table).
  6. Recommended file structure for implementation

    main

    To maintain a clear separation of concerns, the project recommends a modular structure. The architecture is divided into five layers:

    1. API Layer (src/api/): Handles all communication with the backend (e.g., add-entity.ts, fetch-entities.ts).
    2. Core Components (src/components/data-table/): Reusable building blocks like data-table.tsx, pagination.tsx, and toolbar.tsx.
    3. Implementation (src/app/(section)/entity-table/): Entity-specific configuration, including columns.tsx and row-actions.tsx.
    4. Schema (src/app/(section)/entity-table/schema/): Zod type definitions and entity schemas.
    5. Utils (src/components/data-table/utils/): Helper functions for column sizing, date formatting, URL state, and more.
    src/
    ├── api/                       # API integration layer
    ├── components/                # Shared UI components
    └── 📁data-table               # Core data table components
        ├── 📁hooks                # Custom React hooks
        └── 📁utils                # Utility functions and helpers
    
    ├── app/                       # Application routes
        └── 📁entity-table/        # Entity-specific implementation
            ├── 📁components/       # Entity table components (columns, actions)
            ├── 📁schema/           # Data schemas (Zod)
            └── 📁utils/            # Implementation-specific utils
  7. How subrows (hierarchical data) work

    main

    The DataTable supports hierarchical data through the subRowsConfig property. This allows you to display parent-child relationships (e.g., an Order and its Items) using one of three rendering modes:

    1. same-columns: Parent and subrows share the same column structure. The data must contain a subRows array (or a custom field specified by subRowsField).
    2. custom-columns: Parent and subrows use different column definitions. You must provide getColumns for the parent and getSubRowColumns for the subrows.
    3. custom-component: You provide a custom React component via SubRowComponent to handle the rendering of subrow data entirely.

    To enable cross-page selection (selecting items across different pages of data), you must implement and provide the fetchByIdsFn prop.

    <DataTable<Order, unknown>
      getColumns={getColumns}
      fetchDataFn={fetchOrders}
      fetchByIdsFn={fetchOrdersByIds}
      exportConfig={exportConfig}
      subRowsConfig={{
        enabled: true,
        mode: "same-columns", // or "custom-columns" or "custom-component"
      }}
    />
  8. Recommended project file structure

    main

    To maintain a clean separation of concerns, the following structure is recommended when implementing an entity-specific table:

    src/
    ├── api/                       # API integration layer (add, delete, fetch)
    ├── components/                # Shared UI components
    ├── 📁data-table               # Core data table components (hooks, utils, main components)
    │   └── 📁hooks                # Custom React hooks (e.g., use-table-column-resize.ts)
    │   └── 📁utils                # Table utilities (export, date-format, url-state, etc.)
    │   └── data-table.tsx         # Main component entry point
    │   └── ...                    # Other core components (pagination, toolbar, etc.)
    └── app/
        └── (section)/
            └── entity-table/      # Your specific implementation
                ├── components/    # Entity-specific columns, row actions, and popups
                ├── schema/        # Zod/TypeScript definitions for the entity
                └── utils/          # Entity-specific config and data fetching hooks
    src/
    ├── api/                       # API integration layer
    │   └── entity/                # Entity-specific API functions
    │       ├── add-entity.ts      # Create operation
    │       ├── delete-entity.ts   # Delete operation
    │       ├── fetch-entities.ts  # List operation with filters
    │       └── fetch-entity-by-ids.ts # Fetch specific entities
    │
    ├── components/                # Shared UI components
    └── 📁data-table               # Core data table components
        └── 📁hooks                # Custom React hooks for data-table
        └── 📁utils                # Utility functions and helpers
        └── data-table.tsx         # Main data table component
        └── ...
    │
    ├── app/
    │   └── (section)/
    │       └── entity-table/      # Entity-specific implementation
    │           ├── components/    # Entity table components
    │           ├── schema/        # Data schemas
    │           └── utils/         # Table configuration and data fetching
  9. Add calculated columns to exports

    main

    Calculated columns are created by returning new keys in the transformFunction. You can perform mathematical calculations, time-based logic, or business categorization.

    Examples of logic types:

    • Mathematical: Calculating averages or markups (e.g., average_expense: amount / count).
    • Time-based: Calculating tenure (e.g., years_as_customer: currentYear - joinYear).
    • Categorization: Assigning tiers or segments (e.g., spending_tier: amount > 2000 ? 'PREMIUM' : 'STANDARD').
    • Privacy: Masking sensitive data (e.g., email_masked: email.replace(/(.{2}).*@/, "$1****@")).
    const transformFunction = (row: User) => {
      const expenseAmount = parseFloat(row.total_expenses) || 0;
      return {
        ...row,
        average_expense: expenseAmount / Math.max(row.expense_count, 1),
        spending_tier: expenseAmount > 2000 ? "PREMIUM" : "STANDARD"
      };
    };
  10. Key features of the Data Table

    main

    The component provides a comprehensive suite of features categorized into three main areas:

    Data Management

    • Server-side pagination, sorting, and filtering
    • Single & multi-row selection
    • Optimistic UI updates

    UI Features

    • Responsive layout and column resizing
    • Column visibility toggling
    • Date range filtering and search functionality
    • Customizable toolbar, row actions menu, and bulk action support

    Operations

    • CRUD operations: Add new records, edit existing records, and delete single records
    • Bulk delete operations
    • Data export (CSV/Excel)

    Integrations

    • React Query for data fetching
    • Zod for validation
    • React Hook Form for form handling
    • Sonner for toast notifications
    • URL state persistence
  11. Understand server-side filtering and sorting API parameters

    main

    The data table communicates with your API using parameters that automatically match the case format of your column accessorKey definitions.

    Sorting Parameters:

    • sortBy or sort_by: The column to sort by.
    • sortOrder or sort_order: The direction ("asc" or "desc").

    Filtering Parameters:

    • search: The text search term.
    • from_date: Start date in ISO format (for date range filtering).
    • to_date: End date in ISO format (for date range filtering).

    Pagination Parameters:

    • page: Current page number (1-based).
    • limit: Number of items per page.
  12. How the DataTable component works

    main

    The DataTable is a high-level orchestrator that manages the following responsibilities:

    • State Management: Handles internal table state.
    • Data Fetching: Uses the provided fetchDataFn (which must be a React Query hook with .isQueryHook = true) and fetchByIdsFn.
    • URL State: Persists table state (like filters or sorting) to the URL.
    • Features: Manages pagination, sorting, filtering, row selection, and column visibility.
    • Export: Provides functionality to export data based on the provided exportConfig.

    It relies on several sub-components:

    • DataTableColumnHeader: For sorting UI and visual indicators.
    • Filter Components: UI for search and date ranges.
    • Toolbar Components: For global actions and view options.
    • Row Actions: For per-row operations like edit or delete.