diff --git a/.changeset/metal-horses-teach.md b/.changeset/metal-horses-teach.md new file mode 100644 index 00000000000..1d9848855fc --- /dev/null +++ b/.changeset/metal-horses-teach.md @@ -0,0 +1,7 @@ +--- +'@primer/react': minor +--- + +Add suport for sparse sorting to DataTable + + diff --git a/src/DataTable/__tests__/DataTable.test.tsx b/src/DataTable/__tests__/DataTable.test.tsx index 085b1d93ecb..ce7c9d98c23 100644 --- a/src/DataTable/__tests__/DataTable.test.tsx +++ b/src/DataTable/__tests__/DataTable.test.tsx @@ -551,6 +551,81 @@ describe('DataTable', () => { }) }) + it('should sort sparsely populated columns with blank values at the end', async () => { + const user = userEvent.setup() + + render( + , + ) + + const header = screen.getByRole('columnheader', { + name: 'Value', + }) + expect(header).toHaveAttribute('aria-sort', 'ascending') + + // Change to descending + await user.click(screen.getByText('Value')) + + let rows = screen + .getAllByRole('row') + .filter(row => { + return queryByRole(row, 'cell') + }) + .map(row => { + const cell = getByRole(row, 'cell') + return cell.textContent + }) + + expect(rows).toEqual(['3', '2', '1', '', '']) + + // Change to ascending + await user.click(screen.getByText('Value')) + + rows = screen + .getAllByRole('row') + .filter(row => { + return queryByRole(row, 'cell') + }) + .map(row => { + const cell = getByRole(row, 'cell') + return cell.textContent + }) + + expect(rows).toEqual(['1', '2', '3', '', '']) + }) + it('should change the sort direction on mouse click', async () => { const user = userEvent.setup() render( diff --git a/src/DataTable/useTable.ts b/src/DataTable/useTable.ts index cf9579a8764..c9a6b874cc1 100644 --- a/src/DataTable/useTable.ts +++ b/src/DataTable/useTable.ts @@ -116,7 +116,8 @@ export function useTable({ } /** - * Sort the rows of a table with the given column sort state + * Sort the rows of a table with the given column sort state. If the data in the table is sparse, + * blank values will be ordered last regardless of the sort direction. */ function sortRows(state: Exclude) { const header = headers.find(header => { @@ -156,12 +157,23 @@ export function useTable({ const valueA = get(a, header.column.field) const valueB = get(b, header.column.field) - if (state.direction === SortDirection.ASC) { + if (valueA && valueB) { + if (state.direction === SortDirection.ASC) { + // @ts-ignore todo + return sortMethod(valueA, valueB) + } // @ts-ignore todo - return sortMethod(valueA, valueB) + return sortMethod(valueB, valueA) + } + + if (valueA) { + return -1 + } + + if (valueB) { + return 1 } - // @ts-ignore todo - return sortMethod(valueB, valueA) + return 0 }) }) }