import { DataTable } from '@uhg-abyss/web/ui/DataTable';import { useDataTable } from '@uhg-abyss/web/hooks/useDataTable';Initial columns and data
The initialColumns property specifies the columns to display in the table on the first render. It accepts an array of objects, each of which must contain the header and accessorKey values.
{ header: string; accessorKey: string;}The initialData property determines the entries to display in the table on the first render. It accepts an array of objects, where each object represents a row. Each row must have a unique identifier field. By default, the table expects this field to be named uniqueId, but you can specify a different field name using the rowIdKey prop.
{ uniqueId: string; // Default identifier field [accessorKey: string]: any; // Other properties can be added as needed}Here is an example using the default uniqueId field:
[ { uniqueId: '1dc47178-a614-4fcf-8511-ae05bc9bf511', col1: 'Col 1/Row 1', col2: '12/31/2022', col3: 0, col4: 'Completed', }, { uniqueId: '4109763d-9cea-4cbc-8a17-973b01c484e2', col1: 'Col 1/Row 2', col2: '1/1/2023', col3: 1, col4: 'In Progress', },];Using a custom ID field
If your data uses a different field name for the unique identifier, specify it with the rowIdKey prop:
// Data with custom ID fieldconst data = [ { applicationGuid: 'abc-123', col1: 'Row 1', col2: 'Data' }, { applicationGuid: 'def-456', col1: 'Row 2', col2: 'Data' },];
const dataTableProps = useDataTable({ initialData: data, initialColumns: columns, rowIdKey: 'applicationGuid', // Specify your custom ID field});Note: When using TypeScript, rowIdKey is automatically required if your data type lacks a uniqueId field. This compile-time enforcement prevents configuration errors. See Types documentation for details.
Why row identifiers matter
The unique identifier field (whether uniqueId or a custom field via rowIdKey) is critical for DataTable to efficiently track and manage row state. It's used for:
Direct features:
Behind the scenes:
If using data from a remote API, ensure your back-end provides a stable unique identifier for each row.
Basic example
Use the initialData and initialColumns in combination to set the initial state of your DataTable.
Updating data
Use the setColumns and setData methods to update the columns and rows in the table. Do not mutate initial state data as a way to update data on the client side.
Note: These methods are not compatible with server-side pagination.
A second parameter of type boolean can be passed to setColumns and setData to skip page reset; the default is false.
- Note: If you click "Update Data (Skip Page Reset)", you will see an issue with it staying on a blank page.
- Reason: Skipping the page reset can cause the table to display outdated or incorrect data, leading to potential issues with data consistency and user experience.
Data defaults and overrides
By default, `DataTableautomatically left-aligns all values.
Teams can oveDataTablebehavior on a per-column basis by using the column definition's meta property and providing a custom textAlign value:
If you want to turn a column into a row header, pass the isRowHeader: true prop to an individual column meta property.
{ header: 'Column 1', accessorKey: 'col1', meta: { textAlign: 'center', // 'left' | 'right' | 'center' isRowHeader: true, },},Downloading data
The DataTable.DownloadDropdown sub-component provides a dropdown menu for downloading data from the table. It can be used to export data in CSV format, and it can be customized with various download options.
<DataTable.DownloadDropdown />Standard export options
Abyss has three built-in export options:
'exportAllData'- Exports all data in the table.'exportVisibleData'- Exports all visible data displayed. If using pagination, it will export only the current page.'exportFilteredData'- Exports data with sorting and filtering rules applied. If using pagination, it will export all pages.
const dropdownMenuItems = [ { title: 'Example Data', onClick: 'exportAllData', // 'exportAllData' | 'exportVisibleData' | 'exportFilteredData' csvFilename: 'example_data.csv', icon: <IconSymbol icon="example_icon" />, },];
<DataTable.DownloadDropdown dropdownMenuItems={dropdownMenuItems} />;Note:
- When using drag-and-drop columns, the current column order will be reflected in the exported CSV file.
- Hidden columns will not be included in the exported CSV file.
Refer to the Custom download options section below to learn more about advanced export configuration.
Remove CSV columns
Use the removeCsvColumns prop to remove columns from the built-in export options. This prop accepts an array containing the accessorKey values from the columns you would like removed.
Note: Predefined columns such as the row reordering handle, row selection checkboxes, individual action buttons, etc. will be removed by default.
<DataTable.DownloadDropdown removeCsvColumns={['col1', 'col3']} dropdownMenuItems={dropdownMenuItems}/>Custom CSV cell
The customSetCellCsv property is a function that returns the cell value (within a value property) when downloading the table data CSV file. Use this whenever you're performing any custom rendering within the cell to ensure the data is also properly rendered within the CSV.
const renderColData = (value) => { const { colName, rowName } = value; return `${colName} / ${rowName}`;};
{ header: 'Column 1', accessorKey: 'col1', cell: (props) => { const value = props.getValue(); const renderedValue = renderColData(value); return renderedValue; }, meta: { customSetCellCsv: ({ value }) => { return renderColData(value); }, },},Download the CSV file example below to see the use case of prop and how the column without customSetCellCsv attempts to render the full object.
Custom download options
Teams looking for anything more advanced than the basic exports should be looking at this section. Teams are free to export the data however they see fit. One option is to use the downloadCsv utility from @uhg-abyss/web/tools/downloadCsv.
To create a custom download option, provide a function to the menu item's onClick property. The handler receives the table instance for advanced exports.
Note: Using a custom function means that you will be responsible for handling the data export logic. This means the csvFilename and removeCsvColumns props are not applicable.
const dropdownMenuItem = { title: 'Custom Export Example', onClick: (tableInstance) => { // Use the tableInstance to access the current state of the table, including selected rows, columns, filters, etc. downloadCsv({ columns: //..., data: //..., filename: 'custom-download-csv', }); }, icon: <IconSymbol icon="download_2" />,};This example below uses downloadCsv to generate a CSV and the jsPDF library to generate a PDF. Try selecting some rows and then clicking the "Custom Export PDF" / "Custom CSV Export" option in the download dropdown to see how it works!
Disclaimer: The PDF generated is not accessible and is just a simple example of what can be done. Teams looking to implement a PDF export should work with their accessibility teams to ensure the generated file meets accessibility standards.
Component Tokens
Note: Click on the token row to copy the token to your clipboard.
DataTable Tokens
| Token Name | Value | |
|---|---|---|
| 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) |