Skip to content

Console [CNS-34]: Tanstack table in the console#36350

Open
leedqin wants to merge 2 commits intoMaterializeInc:mainfrom
leedqin:console-tanstack-table
Open

Console [CNS-34]: Tanstack table in the console#36350
leedqin wants to merge 2 commits intoMaterializeInc:mainfrom
leedqin:console-tanstack-table

Conversation

@leedqin
Copy link
Copy Markdown
Contributor

@leedqin leedqin commented May 1, 2026

Motivation

We need to add some sorting, filtering capabilities for our console tables. Tanstack tables let us do that without rethinking our current UI designs and it is very easy to integrate with existing table components. TanStack table is a headless UI library that provides powerful abstractions for sorting, filtering, and global search. This implementation wraps TanStack Table with Chakra UI components to maintain the visual elements while also TanStack's headless UI capabilities.

Linear Issue CNS-34

Core Components

File Purpose/Use
UniversalTable.ts React hook wrapping TanStack's useReactTable with sensible defaults for sorting, filtering, pagination, and pinning
UniversalTable.tsx Main rendering component that maps TanStack table state to Chakra UI <Table> components. Handles headers, rows, sorting indicators, loading skeletons, and sticky columns
TablePagination.tsx Pagination controls showing "Showing X-Y of Z" and prev/next buttons. Auto-hides when data fits on one page
TableSearch.tsx Debounced search input that integrates with TanStack's global filter. Includes search icon and clear button
tableColumnBuilders.ts Utilities including sortingFunctions.nullsLast for nullable columns and filterFunctions.globalTextFilter for cross-column search
tableTypes.ts TypeScript interfaces including TableVariant, UniversalTableProps, and module augmentation for ColumnMeta (adds tooltip, isTruncated, minWidth)
guide-tanstack-table.md Developer guide with usage examples, migration steps, and troubleshooting
'
  • Added core table components and hooks wrapping TanStack Table with Chakra UI
  • Migrated ClustersList as the first table using the new implementation
  • Added documentation guide and tests

Partial Fixes MaterializeInc/database-issues#11176, MaterializeInc/database-issues#10108

This will make navigating tables/ pages with a lot of objects especially Clusters page that customers can benefit from sorting and searching for clusters.

How do you feel about this change? (Tips for the reviewer)

Pretty good! I have migrated Clusters List to the Tanstack table.I would recommend reading the testing guide first before reviewing the code. Demo video: https://materializeinc.slack.com/files/U08QMH7H6TC/F0A2EV4REUC/cluster_table.mov

image

Addressed feedback from this console PR:

  • Fixed bug for comment where dynamic data in the columns caused objects to remount.
  • Use Lodash debounce
  • use UniversalDebounce is a more minimal hook especially removed the enablePagination prop and other enable configurations
  • Deleted some brittle tests and assertions
  • Removed pinning in the component
  • Addressed nits:
    • [Using currentPage variable instead of pageIndex+1](https://github.com/MaterializeInc/console/pull/3872#discussion_r2682670127)
    • Relative units for styling instead of using "px"

-  TanStack Table UniversalTable component with a loading skeleton, column headers. sort icons and wraps it around the basic chakra variants
-  `useUniversalTable` hook to expose basic TanStack table API defaults for sorting, searching and pagination
- tableColumnBuilders have basic search and sorting functions for the table data. Unit tests for these functions are in the test file
- TablePagination is a pagination component  for the table
- TableSearch -- search the rows across the table using lodash debounce
- TableTypes for basic table variants, UniversalTableProps and table search props
- tanstack table guide for documenting tanstack table usage
@leedqin leedqin requested a review from a team as a code owner May 1, 2026 18:40
@leedqin leedqin requested review from SangJunBak and removed request for a team May 1, 2026 18:40
@leedqin leedqin force-pushed the console-tanstack-table branch from 4535c40 to 0c796a3 Compare May 1, 2026 18:40
@leedqin leedqin added the A-CONSOLE Area: Console label May 1, 2026
- Clusters table is now paginated with sorting functionalities for the columns, search for the clusters and cluster names showing up as links
@leedqin leedqin force-pushed the console-tanstack-table branch from 0c796a3 to ebc1bc0 Compare May 1, 2026 19:09
Comment on lines +169 to +170
// Static columns: defined at module scope so the table never remounts on
// data refresh. Dynamic data is fetched inside cell components.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like we don't need this comment

Comment on lines +30 to +33
const currentPage = pageIndex + 1;
const from = pageIndex * pageSize + 1;
const to = Math.min(currentPage * pageSize, totalRows);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like we should keep variables zero-indexed then in the view, represent it as 1-indexed.

if (a == null) return 1;
if (b == null) return -1;

return String(a).localeCompare(String(b), undefined, { numeric: true });
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoa didn't know this existed. Super cool!

return columns.some((cell) => {
const value = cell.getValue();
if (value == null) return false;
return String(value).toLowerCase().includes(search);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JSX might get caught in this search

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can imagine as a default filter, this would be okay. Any reason why we couldn't use the builtin ones https://tanstack.com/table/v8/docs/framework/react/examples/filters-fuzzy?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-CONSOLE Area: Console

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants