@@ -307,6 +449,8 @@ const TableContent = <
})
}
+ const expandAllBtnStickyConfig = getStickyColumnConfig(gridTemplateColumns, 0)
+
return (
+ {isAnyRowExpandable ? (
+
+
+ }
+ ariaLabel="Expand/Collapse all rows"
+ showAriaLabelInTippy={false}
+ variant={ButtonVariantType.borderLess}
+ size={ComponentSizeType.xs}
+ style={ButtonStyleType.neutral}
+ onClick={toggleExpandAll}
+ />
+
+ ) : null}
+
{visibleColumns.map(
(
{
@@ -346,6 +514,7 @@ const TableContent = <
size,
showTippyOnTruncate,
horizontallySticky: isStickyColumn,
+ infoTooltipText,
},
index,
) => {
@@ -353,7 +522,12 @@ const TableContent = <
const isBulkActionGutter = field === BULK_ACTION_GUTTER_LABEL
const horizontallySticky = isStickyColumn || isBulkActionGutter
const { className: stickyClassName = '', left: stickyLeftValue = '' } =
- horizontallySticky ? getStickyColumnConfig(gridTemplateColumns, index) : {}
+ horizontallySticky
+ ? getStickyColumnConfig(
+ gridTemplateColumns,
+ index + (isAnyRowExpandable ? 1 : 0),
+ )
+ : {}
if (field === BULK_ACTION_GUTTER_LABEL) {
return (
@@ -379,7 +553,7 @@ const TableContent = <
return (
@@ -392,6 +566,7 @@ const TableContent = <
triggerSorting={getTriggerSortingHandler(field)}
showTippyOnTruncate={showTippyOnTruncate}
disabled={areFilteredRowsLoading}
+ infoTooltipText={infoTooltipText}
{...(isResizable
? { isResizable, handleResize, id: label }
: { isResizable: false })}
diff --git a/src/Shared/Components/Table/constants.ts b/src/Shared/Components/Table/constants.ts
index 1b7ed8b0f..63005f738 100644
--- a/src/Shared/Components/Table/constants.ts
+++ b/src/Shared/Components/Table/constants.ts
@@ -29,3 +29,5 @@ export const DRAG_SELECTOR_IDENTIFIER = 'table-drag-selector'
export const SHIMMER_DUMMY_ARRAY = [1, 2, 3]
export const NO_ROWS_OR_GET_ROWS_ERROR = new Error('Neither rows nor getRows function provided')
+
+export const ACTION_GUTTER_SIZE = 24
diff --git a/src/Shared/Components/Table/styles.scss b/src/Shared/Components/Table/styles.scss
index ed2fb7c1e..ecc29cb3f 100644
--- a/src/Shared/Components/Table/styles.scss
+++ b/src/Shared/Components/Table/styles.scss
@@ -40,6 +40,13 @@
left: -20px;
width: 20px;
}
+
+ &.expand-row-btn::before,
+ &.row-start-icon::before,
+ &.expanded-tree-libe::before {
+ left: -24px;
+ width: 24px;
+ }
}
&--scrolled {
@@ -94,6 +101,33 @@
display: inherit;
}
}
+
+ &.with-start-icon-and-bulk-or-expand-action {
+ .bulk-action-checkbox {
+ display: none;
+ }
+
+ .expand-row-btn {
+ display: none;
+ }
+
+ &:hover,
+ &.generic-table__row--active,
+ &.generic-table__row--bulk-selected,
+ &.generic-table__row--is-expanded {
+ .row-start-icon {
+ display: none;
+ }
+
+ .bulk-action-checkbox {
+ display: flex;
+ }
+
+ .expand-row-btn {
+ display: flex;
+ }
+ }
+ }
}
.sortable-table-header__resize-btn:hover,
@@ -105,4 +139,14 @@
transform: scaleY(var(--resize-btn-scale-multiplier));
}
}
+
+ .expanded-tree-line::after {
+ content: '';
+ width: 1px;
+ height: 100%;
+ background: var(--N200);
+ left: calc(50% - 1px); // offset to left by width for perfect centering
+ top: 0;
+ position: absolute;
+ }
}
diff --git a/src/Shared/Components/Table/types.ts b/src/Shared/Components/Table/types.ts
index 0d729b82a..ddf7f27ea 100644
--- a/src/Shared/Components/Table/types.ts
+++ b/src/Shared/Components/Table/types.ts
@@ -26,6 +26,7 @@ import {
import { GenericEmptyStateType } from '@Common/index'
import { PageSizeOption } from '@Common/Pagination/types'
import { SortableTableHeaderCellProps, useResizableTableConfig } from '@Common/SortableTableHeaderCell'
+import { IconsProps } from '@Shared/Components/Icon'
import { useBulkSelection, UseBulkSelectionProps } from '../BulkSelection'
@@ -87,13 +88,23 @@ type BaseColumnType = {
size: SizeType
horizontallySticky?: boolean
-}
+} & Pick
-export type RowType = {
+type CommonRowType = {
id: string
data: Data
}
+export type ExpandedRowPrefixType = 'expanded-row-'
+
+export type ExpandedRowType = CommonRowType & {
+ id: `${ExpandedRowPrefixType}${string}`
+}
+
+export type RowType = CommonRowType & {
+ expandableRows?: Array>
+}
+
export type RowsType = RowType[]
export enum FiltersTypeEnum {
@@ -117,6 +128,10 @@ export type CellComponentProps<
? UseFiltersReturnType
: UseUrlFiltersReturnType
isRowActive: boolean
+ isExpandedRow: boolean
+ isRowInExpandState: boolean
+ // NOTE: no action if the row is not expandable
+ expandRowCallback: (e: MouseEvent) => void
}
export type RowActionsOnHoverComponentProps<
@@ -307,6 +322,14 @@ export type InternalTableProps<
handleToggleBulkSelectionOnRow: (row: RowType) => void
ViewWrapper?: FunctionComponent>
+
+ /**
+ * An icon as the first element of the row, that hides actions like expand or bulk select icons
+ * until user hovers over the row or the row has focus from keyboard navigation
+ */
+ rowStartIconConfig?: Omit
+
+ onRowClick?: (row: RowType, isExpandedRow: boolean) => void
} & (
| {
/**
@@ -390,6 +413,8 @@ export type TableProps<
| 'ViewWrapper'
| 'pageSizeOptions'
| 'clearFilters'
+ | 'rowStartIconConfig'
+ | 'onRowClick'
>
export type BulkActionStateType = string | null
@@ -440,6 +465,8 @@ export interface TableContentProps<
| 'rowActionOnHoverConfig'
| 'pageSizeOptions'
| 'getRows'
+ | 'rowStartIconConfig'
+ | 'onRowClick'
>,
RowsResultType {
areFilteredRowsLoading: boolean