Skip to main content

DataTable - Sorting

Displays a matrix of information with columns, rows, and information that can operate dynamically.

Submit feedback
github
import { DataTable } from '@uhg-abyss/web/ui/DataTable';
import { useDataTable } from '@uhg-abyss/web/hooks/useDataTable';

Sorting is disabled by default. To enable sorting for all columns, set tableConfig.enableSorting to true.

const dataTableProps = useDataTable({
// ...
tableConfig: {
enableSorting: true,
},
// ...
});

The enableSorting property can also be provided to individual columns for more granular adjustment.

{
header: 'Column 1',
accessorKey: 'col1',
enableSorting: true,
}

To manage the sorting state, provide a function to the tableConfig.onSortingChange property and set the state.sorting property; we recommend using useState for this, as shown below.

const [sorting, setSorting] = useState([]);
const dataTableProps = useDataTable({
// ...
tableConfig: {
enableSorting: true,
onSortingChange: setSorting,
state: {
sorting,
},
},
// ...
});

Built-in sorting

By default, there are six built-in sorting functions to choose from:

  • 'alphanumeric': Sorts by mixed alphanumeric values without case-sensitivity. Slower, but more accurate if your strings contain numbers that need to be naturally sorted.
  • 'alphanumericCaseSensitive': Sorts by mixed alphanumeric values with case-sensitivity. Slower, but more accurate if your strings contain numbers that need to be naturally sorted.
  • 'text': Sorts by text/string values without case-sensitivity. Faster, but less accurate if your strings contain numbers that need to be naturally sorted.
  • 'textCaseSensitive': Sorts by text/string values with case-sensitivity. Faster, but less accurate if your strings contain numbers that need to be naturally sorted.
  • 'datetime': Sorts by time; use this if your values are Date objects.
  • 'basic': Sorts using basic JavaScript value comparison. This is the fastest sorting function, but may not be the most accurate.

To specify the sorting function for a column, use the sortingFn property.

{
header: 'Column 1',
accessorKey: 'col1',
sortingFn: 'alphanumeric',
}

Custom sorting

There may be times when the built-in sorting functions do not meet your needs. In these cases, you can create your own custom sorting functions.

const myCustomSortingFn = (rowA, rowB, columnId) => {
/*
* This is just a simple example to show how to create a custom sorting function,
* but it is generally not recommended to allocate new objects in sorting functions.
* Especially when working with large data sets, this can cause a noticeable performance hit.
* In this example, it would be best if the row data contained `dayjs` objects instead of strings.
*/
const dateA = dayjs(rowA.original[columnId]);
const dateB = dayjs(rowB.original[columnId]);
return dateA.diff(dateB);
};
// ...
{
header: 'Date',
accessorKey: 'col2',
sortingFn: myCustomSortingFn,
},

See the TanStack Table sorting docs for more details.

The example below demonstrates the 'datetime' sorting function not working correctly when the leading zeros are removed from the months and days in the dates and a custom sorting function to sort the dates correctly.

Note: We recommend not using what's in this example to display dates (i.e., directly formatting the date as a string in the column data). Instead, use the cell property of the column to format the date for display. The 'datetime' sorting function works on the underlying data, not the displayed value, so it will sort correctly regardless of how the date is displayed.

Multi-column sorting

Multi-column sorting is disabled by default. To enable multi-column sorting, set tableConfig.enableMultiSort to true. This requires tableConfig.enableSorting to be true as well.

const dataTableProps = useDataTable({
// ...
tableConfig: {
enableSorting: true,
enableMultiSort: true,
},
// ...
});

The enableMultiSort property can also be provided to individual columns for more granular adjustment.

{
header: 'Column 1',
accessorKey: 'col1',
enableMultiSort: true
}

By default, the Shift key is used to trigger multi-column sorting. You can change this behavior with the tableConfig.isMultiSortEvent function. This function receives the event as an argument and should return a boolean value indicating whether the event should trigger multi-column sorting.

const dataTableProps = useDataTable({
// ...
tableConfig: {
isMultiSortEvent: (e) => {
return true; // Always trigger multi-column sorting
},
// or
isMultiSortEvent: (e) => {
return e.ctrlKey || e.shiftKey; // Use the Control or Shift keys to trigger multi-column sorting
},
},
// ...
});

By default, there is no limit to the number of columns that can be sorted at once. Use the tableConfig.maxMultiSortColCount property to specify a limit.

const dataTableProps = useDataTable({
// ...
tableConfig: {
maxMultiSortColCount: 2, // Only allow up to two columns to be sorted at once
},
// ...
});

Here is an advanced multi-column sorting example with a limit of two columns and with multi-column sorting enabled on click.

Component Tokens

Note: Click on the token row to copy the token to your clipboard.

DataTable Tokens

Token NameValue
data-table.color.border.column-header.drag
#002677
data-table.color.border.root
#CBCCCD
data-table.color.border.row.drag
#002677
data-table.color.border.table
#CBCCCD
data-table.color.icon.column-header-menus.grouping.active
#002677
data-table.color.icon.column-header-menus.grouping.hover
#004BA0
data-table.color.icon.column-header-menus.grouping.rest
#196ECF
data-table.color.icon.column-header-menus.sorting.active
#002677
data-table.color.icon.column-header-menus.sorting.hover
#004BA0
data-table.color.icon.column-header-menus.sorting.rest
#196ECF
data-table.color.icon.drag-handle.active
#002677
data-table.color.icon.drag-handle.hover
#004BA0
data-table.color.icon.drag-handle.rest
#196ECF
data-table.color.icon.expander.active
#002677
data-table.color.icon.expander.disabled
#7D7F81
data-table.color.icon.expander.hover
#004BA0
data-table.color.icon.expander.rest
#196ECF
data-table.color.icon.utility.drag-alternative.active
#000000
data-table.color.icon.utility.drag-alternative.disabled
#7D7F81
data-table.color.icon.utility.drag-alternative.hover
#323334
data-table.color.icon.utility.drag-alternative.rest
#4B4D4F
data-table.color.icon.utility.filter.active
#002677
data-table.color.icon.utility.filter.hover
#004BA0
data-table.color.icon.utility.filter.rest
#196ECF
data-table.color.surface.column-header.active
#E5F8FB
data-table.color.surface.column-header.default
#F3F3F3
data-table.color.surface.column-header.drag
#E5F8FB
data-table.color.surface.footer
#F3F3F3
data-table.color.surface.header
#FFFFFF
data-table.color.surface.root
#FFFFFF
data-table.color.surface.row.drag
#E5F8FB
data-table.color.surface.row.even
#FAFCFF
data-table.color.surface.row.highlighted
#E5F8FB
data-table.color.surface.row.hover
#F3F3F3
data-table.color.surface.row.odd
#FFFFFF
data-table.color.surface.table
#FFFFFF
data-table.color.text.cell
#4B4D4F
data-table.color.text.column-header
#4B4D4F
data-table.color.text.header.heading
#002677
data-table.color.text.header.paragraph
#4B4D4F
data-table.border-radius.all.container
8px
data-table.border-width.all.column-header.drag
2px
data-table.border-width.all.root
1px
data-table.border-width.all.row.drag
2px
data-table.border-width.all.table
1px
data-table.sizing.all.icon.column-header-menus
20px
data-table.sizing.all.icon.drag-handle-row
24px
data-table.sizing.all.icon.expander-column
24px
data-table.sizing.all.icon.utility.drag-alternative
20px
data-table.sizing.all.icon.utility.filter
20px
data-table.sizing.height.cell.comfortable
48px
data-table.sizing.height.cell.compact
32px
data-table.sizing.height.cell.cozy
40px
data-table.spacing.gap.horizontal.button-group
8px
data-table.spacing.gap.horizontal.cell
4px
data-table.spacing.gap.horizontal.drag-alternative
8px
data-table.spacing.gap.horizontal.input-container
8px
data-table.spacing.gap.horizontal.slot-wrapper
24px
data-table.spacing.gap.vertical.column-header
2px
data-table.spacing.gap.vertical.header
4px
data-table.spacing.gap.filter-two-inputs
16px
data-table.spacing.padding.all.column-header
8px
data-table.spacing.padding.all.column-header-menus
2px
data-table.spacing.padding.all.header
16px
data-table.spacing.padding.all.result-text
16px
data-table.spacing.padding.all.slot-wrapper
16px
data-table.spacing.padding.horizontal.cell
8px
data-table.spacing.padding.vertical.button-group
8px
data-table.spacing.padding.vertical.cell
4px
data-table.elevation.column.pinned.left
6px 0px 8px -2px rgba(0,0,0,0.16)
data-table.elevation.column.pinned.right
-6px 0px 8px -2px rgba(0,0,0,0.16)
data-table.elevation.column-header
0px 6px 8px -2px rgba(0,0,0,0.16)
data-table.elevation.table-settings-dropdown.section-header
0px 2px 4px -2px rgba(0,0,0,0.16)

Table of Contents