- Table Data Hds
- Examples
- Data Table
- The columns
- Status column with cell‑specific badge styling
- The button column with cell specific actions
- The button column with customisable column width
- The sortable and editable columns
- Nested table inside the parent table
- Customise table’s columns width
- Customise table column alignment (left, center, right)
- Slots
- Properties
- Events
- Custom Properties
- Parts
- Dependencies
Table Data Hds
<sl-table-data-hds> | SlTableDataHds
Data table component to display data in a tabular format.
This component will be removed in V3. Please use the new table-data component.
Examples
Data Table
This component is composed of multiple built-in HDS components. By default, the table includes component-specific columns, rows, and cells for:
- Row selection with checkboxes
- Column sorting in the header
- Inline data input
- Show and hide controls
- Status representation with badges
Some of the HDS component columns, row, and cells are optional, including the row selection, status representation and inline data input.
<sl-table-data-hds id="hds-data-table"></sl-table-data-hds> <script> const dataTable = document.getElementById('hds-data-table'); dataTable.chartTitle = "Special data table" dataTable.rowHover = true; dataTable.striped = true; // NOTE: the 'status' keyword transforms the values into labels dataTable.columns = ['name', 'age', 'city', 'editable input', 'status']; dataTable.sortableColumns = ['name', 'age', 'city', 'editable input', 'status']; dataTable.editableColumns = ['city', 'editable input'] dataTable.data = [ { id: 1, rows: [ 'Alice', 12, 'New York', 'A value that needs to be edited', 'Active' ] }, { id: 2, rows: [ 'Jim', 38, 'Victoria', 'A value that needs to be edited', 'Inactive'] }, { id: 3, rows: [ 'Bob', 50, 'Western AUS', 'A value that needs to be edited', 'Pending'] }, { id: 4, rows: [ 'Peter', 29, 'TN', 'A value that needs to be edited', 'Active'] }, { id: 5, rows: [ 'Joe', 30, 'NSW', 'A value that needs to be edited', 'Active'] }, ]; // Example of capturing data when editing a cell document.getElementById('hds-data-table').addEventListener('cell-edit', (event) => { const { id, rowIndex, colIndex, updatedValue } = event.detail; console.log(`Cell updated record id: ${id} at row ${rowIndex}, column ${colIndex}: ${updatedValue}`); // Handle the update, e.g., save to a server or update local state }); // Example of capturing selected row data document.getElementById('hds-data-table').addEventListener('selection-change', (event) => { const { selectedRowIds } = event.detail; console.log(`Id's of rows selected: ${selectedRowIds}`); // Handle the update, e.g., save to a server or update local state }); // Example of capturing action click on row eye document.getElementById('hds-data-table').addEventListener('row-action', (event) => { const { id } = event.detail; console.log(`Id of row: ${id}`); // Handle the update, e.g., save to a server or update local state }); </script>
The columns
The following columns are visible by default and can be hidden or show when required by adding the corresponding attributes to this component.
Use hide-checkbox-column to hide the row selection checkboxes and/or
hide-action-column to hide the action (icon) column.
<sl-table-data-hds id="hds-data-table-hiding" hide-checkbox-column hide-action-column></sl-table-data-hds> <script> const dataTable = document.getElementById('hds-data-table-hiding'); dataTable.chartTitle = "Data table with hidden columns" dataTable.rowHover = true; dataTable.striped = true; // NOTE: the 'status' keyword transforms the values into labels dataTable.columns = ['name', 'age', 'city']; dataTable.sortableColumns = ['name', 'age', 'city']; dataTable.data = [ { id: 1, rows: [ 'Alice', 12, 'New york' ] }, { id: 2, rows: [ 'Jim', 38, 'Chicago'] }, { id: 3, rows: [ 'Bob', 50, 'Los Vegas']} ]; // Example of capturing selected row data document.getElementById('hds-data-table-hiding').addEventListener('selection-change', (event) => { const { selectedRowIds } = event.detail; console.log(`Id's of rows selected: ${selectedRowIds}`); // Handle the update, e.g., save to a server or update local state }); </script>
Status column with cell‑specific badge styling
The status column uses built‑in functionality provided by sl-badge. Each cell in the status column displays a single badge, with the badge variant determined by the cell’s value. At this stage, three badge variants are supported:
Active: displayed with a green background.
Inactive: displayed with a red background.
Any text other than Active or Inactive : displayed with a yellow background.
The status column can be hidden by omitting the header label from the datatable.columns array.
<sl-table-data-hds id="hds-data-table-status"></sl-table-data-hds> <script> const dataTable = document.getElementById('hds-data-table-status'); dataTable.chartTitle = "Data table with status column" dataTable.rowHover = true; dataTable.striped = true; // NOTE: the 'status' keyword transforms the values into labels dataTable.columns = ['name', 'age', 'status']; dataTable.data = [ { id: 1, rows: [ 'Alice', 12, 'Active'] }, { id: 2, rows: [ 'Jim', 38, 'Inactive' ] }, { id: 3, rows: [ 'Bob', 50, 'Pending' ] } ]; // Example of capturing selected row data document.getElementById('hds-data-table-status').addEventListener('selection-change', (event) => { const { selectedRowIds } = event.detail; console.log(`Id's of rows selected: ${selectedRowIds}`); // Handle the update, e.g., save to a server or update local state }); </script>
The button column with cell specific actions
The button column differs from other columns because it supports column level and row‑level
(cell‑specific) actions. The column is hidden by default. To display it, enable the column using the
show-button-column attribute. When the button column is enabled, each row can
independently control whether a button is rendered.
To hide the button for that row, use { type: 'hidden' }.
To display a button with a custom label and custom button behaviour, use
{ type: 'button', label: 'Your custom label', action: 'Your custom action' }.
If the type is undefined, the default button is displayed.
<sl-table-data-hds id="hds-data-table-button" show-button-column></sl-table-data-hds> <script> const dataTable = document.getElementById('hds-data-table-button'); dataTable.chartTitle = "Data table with button column" dataTable.rowHover = true; dataTable.striped = true; // NOTE: the 'status' keyword transforms the values into labels dataTable.columns = ['name', 'age', 'status']; dataTable.data = [ { id: 1, rows: [ 'Alice', 12, 'Active', { type: 'hidden' } ] }, { id: 2, rows: [ 'Jim', 38, 'Inactive', { type: 'button', label: 'Edit', action: 'edit' } ] }, { id: 3, rows: [ 'Bob', 50, 'Pending', { type: 'button', label: 'Print', action: 'print' } ] } ]; // Example of capturing selected row data document.getElementById('hds-data-table-button').addEventListener('selection-change', (event) => { const { selectedRowIds } = event.detail; console.log(`Id's of rows selected: ${selectedRowIds}`); // Handle the update, e.g., save to a server or update local state }); dataTable.addEventListener('row-action', (e) => { const { id, action } = e.detail; switch (action) { case 'edit': toggleEdit(id) break; case 'print': togglePrint(id) break; default: // fallback break; } }); const editActionHandlers = { 'edit': (id) => toggleEdit(id) }; const printActionHandlers = { 'print': (id) => togglePrint(id) }; function togglePrint(id) { console.log("Hello HUB24") } function toggleEdit(id) { console.log("Edit button is clicked") } </script>
The button column with customisable column width
By default, width of the column is set to 40px. However, it can be controlled using the
--table-data-hds-button-column-width CSS custom property.
<sl-table-data-hds id="hds-data-table-width" style="--table-data-hds-button-column-width: 300px;" show-button-column></sl-table-data-hds> <script> const dataTable = document.getElementById('hds-data-table-width'); dataTable.chartTitle = "Data table with custom column width" dataTable.rowHover = true; dataTable.striped = true; // NOTE: the 'status' keyword transforms the values into labels dataTable.columns = ['name', 'age', 'status']; dataTable.data = [ { id: 1, rows: [ 'Alice', 12, 'Active', { type: 'hidden' } ] }, { id: 2, rows: [ 'Jim', 38, 'Inactive', { type: 'button', label: 'Example', action: 'example' } ] }, { id: 3, rows: [ 'Bob', 50, 'Pending', { type: 'button', label: 'Open', action: 'open' } ] } ]; // Example of capturing selected row data document.getElementById('hds-data-table-width').addEventListener('selection-change', (event) => { const { selectedRowIds } = event.detail; console.log(`Id's of rows selected: ${selectedRowIds}`); // Handle the update, e.g., save to a server or update local state }); dataTable.addEventListener('row-action', (e) => { const { id, action } = e.detail; switch (action) { case 'example': // example row break; case 'open': // remove row break; default: // fallback } }); </script>
The sortable and editable columns
Not all columns need to be sortable. Use dataTable.sortableColumns in your JavaScript to
explicitly define which columns support sorting. If this property is not set, all columns will not be
sortable by default.
To enable inline editing for specific columns, define them using
dataTable.editableColumns.
<sl-table-data-hds id="hds-data-table-sortable-editable"></sl-table-data-hds> <script> const dataTable = document.getElementById('hds-data-table-sortable-editable'); dataTable.chartTitle = "Data table with sortable and editable columns" dataTable.rowHover = true; dataTable.striped = true; // NOTE: the 'status' keyword transforms the values into labels dataTable.columns = ['name', 'age', 'status', 'editable input']; dataTable.sortableColumns = ['name', 'age'] dataTable.editableColumns = ['editable input'] dataTable.data = [ { id: 1, rows: [ 'Alice', 12, 'Active', 'A value that needs to be edited' ] }, { id: 2, rows: [ 'Jim', 38, 'Inactive', 'A value that needs to be edited' ] }, { id: 3, rows: [ 'Bob', 50, 'Pending', 'A value that needs to be edited' ] } ]; // Example of capturing selected row data document.getElementById('hds-data-table-sortable-editable').addEventListener('selection-change', (event) => { const { selectedRowIds } = event.detail; console.log(`Id's of rows selected: ${selectedRowIds}`); // Handle the update, e.g., save to a server or update local state }); </script>
Nested table inside the parent table
Table rows can be expanded optionally using the nestedColumns and
nestedData nested arrays in JavaScript. When a row is expanded, a data table is rendered
within the row body.
When using nested tables, the component is composed of multiple layers to define the data structure. This includes the parent table, which contains the table label row and table content, and a nested table rendered within the parent table content.
To optimise readability and maintain visual balance, a maximum height is applied to the table body. Content that exceeds this height is displayed within a scrollable area.
The nested table header must be defined outside the parent table data, while the nested table content is defined within the parent table content. Refer to the preview below for detailed examples of this structure.
<sl-table-data-hds id="nested-table" hide-checkbox-column hide-action-column show-button-column></sl-table-data-hds> <script> const dataTable = document.getElementById('nested-table'); dataTable.chartTitle = "Nested data table" // NOTE: the 'status' keyword transforms the values into labels dataTable.columns = ['Code', 'Name', 'Quantity', 'Price valuation date', 'status', 'Gross Capital Gain/(Loss)']; const nestedColumns = ['Parcel date', 'Accounting cost base', 'Cost base', 'Market Value', 'Gross Capital Gain/(Loss)'] dataTable.data = [ { id: 1, rows: [ 'ANZ', 'Australia and Name', 00, '12/04/2026', 'Inactive', '$1,000' ], nestedColumns, nestedData: [ { id: 1, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 2, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 3, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 4, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 5, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 6, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 7, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 8, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 9, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 10, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 11, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 12, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 13, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 14, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 15, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, ] }, { id: 2, rows: [ 'APA', 'Australia and Name', 00, '12/04/2026', 'Inactive', '$1,000' ], nestedColumns, nestedData: [ { id: 1, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 2, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 3, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, ] }, { id: 3, rows: [ 'CBA', 'Australia and Name', 00, '12/04/2026', 'Active', '$1,000' ], nestedColumns, nestedData: [ { id: 1, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 2, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 3, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, ] }, { id: 4, rows: [ 'CH01', 'Australia and Name', 00, '12/04/2026', 'Active', '$1,000' ] }, { id: 5, rows: [ 'CH1.05', 'Australia and Name', 00, '12/04/2026', 'Active', '$1,000' ] }, { id: 5, rows: [ 'CH1.2', 'Australia and Name', 00, '12/04/2026', 'Active', '$1,000' ] }, ]; </script>
Customise table’s columns width
The columnWidths property allows you to define custom widths for specific columns in the
table. This property accepts an object where the keys are the column names (or indices as strings),
and the values are objects specifying the width, and optionally, the minWidth and
maxWidth for each column.
If a column is not specified in the columnWidths object, its width will be determined
automatically based on the content and available space.
<sl-table-data-hds id="parent-table"></sl-table-data-hds> <script> const parentTable = document.getElementById('parent-table'); parentTable.chartTitle = "Parent Table with Custom Column Widths"; parentTable.rowHover = true; parentTable.striped = true; // Define columns and data parentTable.columns = ['name', 'age', 'city', 'status']; parentTable.data = [ { id: 1, rows: ['Alice', 25, 'New York', 'Active'] }, { id: 2, rows: ['Bob', 30, 'Los Angeles', 'Inactive'] }, { id: 3, rows: ['Charlie', 35, 'Chicago', 'Pending'] }, ]; // Define custom column widths parentTable.columnWidths = { name: { width: '300px' }, age: { width: '300px' }, city: { width: '300px' }, status: { width: '300px' }, }; </script>
Nested table’s columns width
Similar to the columnWidths property, the nestedColumnWidths property allows
you to define custom widths for specific columns in a nested table. It accepts an object where the
keys are the column names (or indices as strings), and the values specify the width, and optionally,
the minWidth and maxWidth. Columns not specified will adjust automatically based on content and
available space.
<sl-table-data-hds id="nested-table-custom-width"></sl-table-data-hds> <script> const dataTable = document.getElementById('nested-table-custom-width'); dataTable.chartTitle = "Nested data table" // NOTE: the 'status' keyword transforms the values into labels dataTable.columns = ['Code', 'Name', 'Quantity', 'Price valuation date', 'status', 'Gross Capital Gain/(Loss)']; const nestedColumns = ['Parcel date', 'Accounting cost base', 'Cost base', 'Market Value', 'Gross Capital Gain/(Loss)']; // Define custom widths for the nested table columns dataTable.nestedColumnWidths = { 'Parcel date': { width: '300px' }, 'Accounting cost base': { width: '300px' }, 'Cost base': { width: '300px' }, 'Market Value': { width: '300px' }, 'Gross Capital Gain/(Loss)': { width: '300px' } }; dataTable.data = [ { id: 1, rows: [ 'ANZ', 'Australia and Name', 00, '12/04/2026', 'Inactive', '$1,000' ], nestedColumns, nestedData: [ { id: 1, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 2, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 3, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 4, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 5, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 6, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 7, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 8, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 9, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 10, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 11, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 12, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 13, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 14, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 15, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, ] }, { id: 2, rows: [ 'APA', 'Australia and Name', 00, '12/04/2026', 'Inactive', '$1,000' ], nestedColumns, nestedData: [ { id: 1, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 2, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 3, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, ] }, { id: 3, rows: [ 'CBA', 'Australia and Name', 00, '12/04/2026', 'Active', '$1,000' ], nestedColumns, nestedData: [ { id: 1, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 2, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, { id: 3, rows: ['22/01/2026', '$1,000', '$1,000','$1,000', '$1,000'] }, ] }, { id: 4, rows: [ 'CH01', 'Australia and Name', 00, '12/04/2026', 'Active', '$1,000' ] }, { id: 5, rows: [ 'CH1.05', 'Australia and Name', 00, '12/04/2026', 'Active', '$1,000' ] }, { id: 5, rows: [ 'CH1.2', 'Australia and Name', 00, '12/04/2026', 'Active', '$1,000' ] }, ]; </script>
Customise table column alignment (left, center, right)
The columnAlignments property allows you to define the alignment of content for specific
columns in the table. This property accepts an object where the keys are the column names (or indices
as strings), and the values specify the alignment as one of the following options: left,
center, or right.
If a column is not specified in the columnAlignments object, its alignment will default
to left.
<sl-table-data-hds id="hds-data-table-alignment"></sl-table-data-hds> <script> const dataTable = document.getElementById('hds-data-table-alignment'); dataTable.chartTitle = "Data table with custom column alignment"; dataTable.rowHover = true; dataTable.striped = true; dataTable.columns = ['name', 'age', 'city', 'status']; dataTable.data = [ { id: 1, rows: ['Alice', 25, 'Sydney', 'Active'] }, { id: 2, rows: ['Bob', 38, 'Melbourne', 'Inactive'] }, { id: 3, rows: ['Charlie', 29, 'Brisbane', 'Default'] } ]; // left | center | right dataTable.columnAlignments = { name: 'left', age: 'center', city: 'right', status: 'center' }; </script>
Nested table column alignment (left, center, right)
Similar to the columnAlignments property for the parent table, the
nestedColumnAlignments property allows you to define the alignment of content for
specific columns in a nested table. This property accepts an object where the keys are the column
names (or indices as strings), and the values specify the alignment as one of the following options:
left, center, or right.
If a column is not specified in the nestedColumnAlignments object, its alignment will
default to left.
<sl-table-data-hds id="nested-table-alignment" hide-checkbox-column hide-action-column></sl-table-data-hds> <script> const dataTable = document.getElementById('nested-table-alignment'); dataTable.columns = ['Code', 'Name', 'status']; const nestedColumns = ['Parcel date', 'Cost base', 'Market Value']; // parent alignment dataTable.columnAlignments = { Code: 'left', Name: 'left', status: 'center' }; // nested alignment dataTable.nestedColumnAlignments = { 'Parcel date': 'left', 'Cost base': 'right', 'Market Value': 'center' }; dataTable.data = [ { id: 1, rows: ['ANZ', 'Australia and Name', 'Active'], nestedColumns, nestedData: [ { id: 11, rows: ['22/01/2026', '$1,000', '$1,050'] }, { id: 12, rows: ['23/01/2026', '$1,200', '$1,180'] } ] } ]; </script>
[component-metadata:sl-table-data-hds]
Slots
| Name | Description |
|---|---|
| (default) | The default slot. |
Learn more about using slots.
Properties
| Name | Description | Reflects | Type | Default |
|---|---|---|---|---|
data
|
The data to be displayed in the table. |
|
TableData[]
|
[]
|
columns
|
The titles to be displayed in the table header columns. |
string[]
|
[]
|
|
editableColumns
editable-columns
|
Defines which columns will be editable. |
string[]
|
[]
|
|
chartTitle
table-title
|
The title of the data table. |
string
|
''
|
|
rowHover
row-hover
|
Adds hover effect to the table rows. |
boolean
|
false
|
|
striped
|
Adds alternating stripes to the table rows. |
boolean
|
false
|
|
hideCheckboxColumn
hide-checkbox-column
|
Hides the checkbox selection column. |
boolean
|
false
|
|
hideActionColumn
hide-action-column
|
Hides the action column. |
boolean
|
false
|
|
showButtonColumn
show-button-column
|
Shows the button column. |
boolean
|
false
|
|
sortableColumns
sortable-columns
|
Defines which columns are sortable. All columns are unsortable by default. |
string[]
|
[]
|
|
buttonLabel
button-label
|
Default label used when button cell doesn’t override it. |
string
|
'Label'
|
|
columnWidths
|
Defines the widths of the table columns. Example: { name: { width: ’100px’ }, age: { width: ‘50px’ } } |
ColumnWidthsInput
|
{}
|
|
nestedColumnWidths
|
Defines the widths of the nested table columns. Example: { a: { width: ’100px’ }, b: { width: ‘50px’ } } |
ColumnWidthsInput
|
{}
|
|
columnAlignments
|
Defines the alignments of the table columns. Example: { name: ‘left’, age: ‘center’, city: ‘right’ } |
{ [key: string]: 'left' | 'center' | 'right' }
|
{}
|
|
nestedColumnAlignments
|
Defines the alignments of the nested table columns. Example: { a: ‘left’, b: ‘center’, c: ‘right’ } |
{ [key: string]: 'left' | 'center' | 'right' }
|
{}
|
|
updateComplete |
A read-only promise that resolves when the component has finished updating. |
Learn more about attributes and properties.
Events
| Name | React Event | Description | Event Detail |
|---|---|---|---|
cell-edit |
|
event emitted when a cell is edited. | - |
selection-change |
|
event emitted when the selection changes. | - |
row-action |
|
event emitted when a row action is clicked. | - |
Learn more about events.
Custom Properties
| Name | Description | Default |
|---|---|---|
--table-data-hds-button-column-width |
The customisable width of the button column. | |
--table-data-hds-expand-column-width |
The customisable width of the expand control column. | |
--table-data-hds-checkbox-column-width |
The customisable width of the checkbox column. | |
--table-data-hds-action-column-width |
The customisable width of the action column. |
Learn more about customizing CSS custom properties.
Parts
| Name | Description |
|---|---|
base |
The component’s base wrapper. |
table |
The table element. |
Learn more about customizing CSS parts.
Dependencies
This component automatically imports the following dependencies.
<sl-checkbox><sl-icon><sl-icon-button><sl-input>