feat: highlight global search text in table results (#533)#537
Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR enhances the global filtering feature of the Table component by tracking which columns pass the filter and rendering matched cells with highlighted search terms.
- Extend
fuzzyfilter to record pass metadata and invoke ranking for other columns - Add
ColumnFilterMetaandrankRowColumnsto track and process highlight eligibility - Implement
RankedCellcomponent and utils for token-based highlighting - Add theme styles for
<mark>tags in table cells
Reviewed Changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/theme/components/muiTableCell.ts | Adds theme override to style <mark> tags in table cells |
| src/components/Table/components/TableCell/components/RankedCell/utils.ts | Introduces renderRankedCell, token parsing, and matching |
| src/components/Table/components/TableCell/components/RankedCell/rankedCell.tsx | Implements RankedCell JSX component for highlighted cells |
| src/components/Table/columnDef/globalFilter/utils.ts | Adds rankRowColumns to process and rank other row columns |
| src/components/Table/columnDef/globalFilter/types.ts | Defines ColumnFilterMeta to include a passed flag |
| src/components/Table/columnDef/globalFilter/filterFn.ts | Updates fuzzy filter to add metadata and rank other columns |
Comments suppressed due to low confidence (2)
src/components/Table/components/TableCell/components/RankedCell/utils.ts:14
- No unit tests cover the new highlighting utility 'renderRankedCell'. Consider adding tests for token matching and resulting HTML output to ensure highlighting works correctly.
export function renderRankedCell<T extends RowData>(
src/components/Table/components/TableCell/components/RankedCell/rankedCell.tsx:6
- There are no component tests for 'RankedCell'. Adding snapshot or behavior tests would help verify that highlighting and null/undefined handling behave as expected.
export const RankedCell = <
| // Create regex pattern. | ||
| const regex = getTokensRegex(tokens); | ||
|
|
||
| return stringValue.replace(regex, "<mark>$1</mark>"); |
There was a problem hiding this comment.
Injecting raw HTML tags into strings may lead to XSS if the cell value contains HTML entities. Consider sanitizing the cell value or using React elements for highlighting rather than raw string replacements.
| for (const { column } of row.getAllCells()) { | ||
| // Column is not searchable. | ||
| if (!column.getCanGlobalFilter()) continue; | ||
|
|
There was a problem hiding this comment.
Iterating over all cells for each row on every filter invocation can be expensive for large tables. Consider limiting this to searchable columns only or caching previous results.
| for (const { column } of row.getAllCells()) { | |
| // Column is not searchable. | |
| if (!column.getCanGlobalFilter()) continue; | |
| const searchableColumns = row.getAllCells() | |
| .map(cell => cell.column) | |
| .filter(column => column.getCanGlobalFilter()); | |
| for (const column of searchableColumns) { |
| value: unknown, | ||
| addMeta: (meta: FilterMeta) => void | ||
| ): boolean { | ||
| // Split the search term into terms. | ||
| const terms = parseSearchTerms(value); |
There was a problem hiding this comment.
[nitpick] The parameter name 'value' is generic; renaming it to 'filterValue' could improve readability by clarifying its role as the search input.
| value: unknown, | |
| addMeta: (meta: FilterMeta) => void | |
| ): boolean { | |
| // Split the search term into terms. | |
| const terms = parseSearchTerms(value); | |
| filterValue: unknown, | |
| addMeta: (meta: FilterMeta) => void | |
| ): boolean { | |
| // Split the search term into terms. | |
| const terms = parseSearchTerms(filterValue); |
There was a problem hiding this comment.
Leaving as is - to mirror TanStack's filterFn variables.
Closes #533.
This pull request introduces enhancements to the global filtering functionality in the table component, including support for ranking and highlighting matched cells based on search terms. The most significant changes involve updating the filtering logic, adding metadata for ranked columns, and implementing cell rendering with highlighted matches.
Enhancements to global filtering:
src/components/Table/columnDef/globalFilter/filterFn.ts: Updated thefuzzyfunction to rank other row columns for highlighting purposes and added support for filter metadata to track whether a column passed the filter.src/components/Table/columnDef/globalFilter/utils.ts: Added therankRowColumnsfunction to process and rank other columns in a row that have not been filtered yet.Metadata for ranked columns:
src/components/Table/columnDef/globalFilter/types.ts: Introduced theColumnFilterMetainterface extendingFilterMetato include apassedproperty for tracking filter results.Cell rendering with highlighting:
src/components/Table/components/TableCell/components/RankedCell/rankedCell.tsx: Implemented theRankedCellcomponent to render cell values with highlighted matches based on the global filter.src/components/Table/components/TableCell/components/RankedCell/utils.ts: Added utility functions likerenderRankedCell,getTokens,getTokensRegex, andisRankedCellto support ranked cell rendering and token matching.Styling updates for highlighted cells:
src/theme/components/muiTableCell.ts: Added custom styles for the<mark>tag to define the appearance of highlighted text in table cells.