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
})
})
}