Skip to main content

DataTable - Columns

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';

Column properties

You can modify the displayed header by using the header property in the column configuration. This accepts either a string, for a basic header, or a function, for more customization.

Note: If header (or the function return value) is not a string value, you must also use the headerLabel property for accessibility and configuration reasons.

{
header: () => {
return (
<React.Fragment>
<IconSymbol icon="home" size="24px" />
Home Column
</React.Fragment>
);
},
accessorKey: 'col1',
meta: {
headerLabel: 'Home Column',
},
}

Row headers (accessibility requirement)

For accessibility purposes, you will need to define which column best labels the contents of its row. This changes cells in that column from <th> to <th scope="row"> to help screen reader users more clearly understand data in that row.

const dataTableProps = useDataTable({
// ...
initialColumns: [
{
header: 'Name',
accessorKey: 'name',
meta: {
isRowHeader: true,
},
},
// ...
],
// ...
});

Cell

Use the cell property to modify the display value of the cells in a column. If the cell property is not used, the cell will simply display the data value.

Note: By default, all built-in sorting and filtering is performed on the underlying data itself. Refer to the Cell filtering and sorting section for more information.

{
header: 'Column 1',
accessorKey: 'col1',
cell: (props) => {
const value = props.getValue();
return (
<React.Fragment>
<IconSymbol icon="home" size="24px" />
{value}
</React.Fragment>
);
},
}

Use the footer property to add a footer to the column. Like header, this accepts either a string, for a basic footer, or a function, for more customization.

{
header: 'Column 1',
accessorKey: 'col1',
footer: 'Footer 1',
}

By default, the column footer is not sticky. To enable this behavior, set the stickyFooter prop to true on the table component.

return (
// ...
<DataTable.Table stickyFooter={false} />
// ...
);

Cell filtering and sorting

When using only the cell property to format display values, all built-in sorting and filtering operations will still use the original underlying data. For formatted values (like dates or currency) to work properly with sorting and filtering, use the accessorFn property to transform the data at the source level.

Here are two examples that show it being used and working correctly and the other not working correctly (not using accessorFn).

Note: cell should primarily be used for display purposes only. If you need to format the data for sorting or filtering, use accessorFn instead.

// Correct setup
{
header: 'Formatted Date',
accessorKey: 'col2',
accessorFn: (row) => dayjs(row.col2).format('MMMM D, YYYY'),
},
// Incorrect setup
{
header: 'Formatted Date',
accessorKey: 'col2',
cell: ({ getValue }) => {
return dayjs(getValue()).format('MMMM D, YYYY');
},
},

Still need more control over filtering and sorting? Refer to our custom sorting and filtering examples

Column configuration

Column width

By default, all columns have a width of 175px. To override this default value and/or to specify minimum or maximum widths, use the tableConfig.defaultColumn property. This property accepts an object with the following properties:

  • minSize: The minimum width of the column.
  • size: The default width of the column.
  • maxSize: The maximum width of the column.
const dataTableProps = useDataTable({
// ...
tableConfig: {
defaultColumn: {
size: 200,
minSize: 100,
maxSize: 300,
},
},
// ...
});

maxSize, size, and minSize can also be provided to individual columns for more granular adjustment.

{
header: 'Column 1',
accessorKey: 'col1',
minSize: 100,
size: 150,
maxSize: 300,
}

Customizing column order

To change the order of the columns, use the initialColumnOrder property of the initialStateConfig object.

Note: initialColumnOrder should be an array of ALL column IDs. Columns managed by Abyss will be prefixed with 'abyss-'.

const dataTableProps = useDataTable({
// ...
initialStateConfig: {
initialColumnOrder: ['col4', 'abyss-reorder-row', 'col3', 'col2', 'col1'],
// ...
},
});

To programmatically change the column order, use the setColumnOrder method.

const dataTableProps = useDataTable({
// ...
});
const reorderColumns = () => {
const newOrder = ['col4', 'col3', 'col2', 'abyss-reorder-row', 'col1'];
dataTableProps.columnOrderState.setColumnOrder(newOrder);
};
// ...
return <Button onClick={reorderColumns}>Reorder Columns</Button>;

Note: Sticky/pinned columns will always appear to the left or right of the table regardless of the specified column order. For instance, in the example below, the abyss-reorder-row column will always be the first column in the table.

Resizing columns

The ability to resize columns is disabled by default. To enable resizing for all columns, set tableConfig.enableResizing to true.

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

enableResizing can also be set on individual columns for more granular control.

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

With the default setting, columnResizeMode: 'onChange', columns resize in real time as you drag the resizer handle.

Note: 'onChange' mode can cause performance issues with large tables, so it is recommended to set tableConfig.columnResizeMode to 'onEnd' for better performance.

Sticky/pinned columns

Sticky (or pinned) columns are columns that remain fixed in place while the rest of the table scrolls. This is useful for keeping important information visible while scrolling through large data sets. To pin columns, use the initialStateConfig.initialPinnedColumns property. This property accepts a left and right array of column accessors.

Note: All Abyss-managed columns are pinned internally, so there is no need to include them in the initialPinnedColumns array. However, they can be included to override the default order and placement.

const dataTableProps = useDataTable({
// ...
initialStateConfig: {
initialPinnedColumns: {
left: ['abyss-reorder-row', 'abyss-select', 'abyss-expand'],
right: ['abyss-edit-action', 'abyss-action'],
},
// ...
},
});

To programmatically change the pinned column order, use the setColumnPinning method.

const dataTableProps = useDataTable({
//...
});
const pinNewColumns = () => {
const newPinning = {
left: ['col1'],
right: ['col4', 'col5'],
};
dataTableProps.columnPinningState.setColumnPinning(newPinning);
};
//...
return <Button onClick={pinNewColumns}>Pin Col1, Col4, and Col5</Button>;

Column display

Table settings dropdown

The DataTable.TableSettingsDropdown subcomponent provides a dropdown menu for editing column visibility and order as well as table density.

<DataTable.TableSettingsDropdown />

By default, empty columns—columns with no content in the cells—are visible by default. This can be changed by setting defaultSettingsConfig.hideEmptyColumns to true.

const dataTableProps = useDataTable({
// ...
defaultSettingsConfig: {
hideEmptyColumns: true,
},
// ...
});

Note: It is not required to use DataTable.TableSettingsDropdown to take advantage of defaultSettingsConfig.hideEmptyColumns. Currently, DataTable.TableSettingsDropdown does not contain a way for users to toggle the visibility of empty columns, so this must be done programmatically.

Programmatically change column visibility

To programmatically change the visibility of columns, provide a function to the tableConfig.onColumnVisibilityChange property and set the state.columnVisibility property; we recommend using useState for this, as shown below.

const [columnVisibility, setColumnVisibility] = useState({
columnId1: true,
columnId2: false,
columnId3: true,
});
const dataTableProps = useDataTable({
//...
tableConfig: {
onColumnVisibilityChange: setColumnVisibility,
state: {
columnVisibility,
},
},
// ...
});

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

{
header: 'Column 4',
accessorKey: 'col4',
enableHiding: false,
}

Note: When enableHiding is set to false, the column visibility checkbox in the table settings dropdown will be disabled. However, it is still possible to hide the column programmatically. To prevent this, you will need to ensure that the column is not included in the columnVisibility state when updating it.

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