@patternfly/react-table 6.5.0-prerelease.8 → 6.5.0-prerelease.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/CHANGELOG.md +298 -0
  2. package/README.md +1 -1
  3. package/components/package.json +1 -1
  4. package/deprecated/package.json +1 -1
  5. package/dist/dynamic/components/Table/package.json +1 -1
  6. package/dist/dynamic/components/Table/utils/decorators/package.json +1 -1
  7. package/dist/dynamic/components/Table/utils/package.json +1 -1
  8. package/dist/dynamic/deprecated/components/Table/base/package.json +1 -1
  9. package/dist/dynamic/deprecated/components/Table/package.json +1 -1
  10. package/dist/dynamic/deprecated/components/package.json +1 -1
  11. package/dist/esm/components/Table/CollapseColumn.js +2 -2
  12. package/dist/esm/components/Table/CollapseColumn.js.map +1 -1
  13. package/dist/esm/components/Table/EditColumn.js +2 -2
  14. package/dist/esm/components/Table/EditColumn.js.map +1 -1
  15. package/dist/esm/components/Table/EditableSelectInputCell.d.ts.map +1 -1
  16. package/dist/esm/components/Table/EditableSelectInputCell.js.map +1 -1
  17. package/dist/esm/components/Table/InnerScrollContainer.d.ts +3 -1
  18. package/dist/esm/components/Table/InnerScrollContainer.d.ts.map +1 -1
  19. package/dist/esm/components/Table/InnerScrollContainer.js +5 -3
  20. package/dist/esm/components/Table/InnerScrollContainer.js.map +1 -1
  21. package/dist/esm/components/Table/SelectColumn.d.ts +2 -0
  22. package/dist/esm/components/Table/SelectColumn.d.ts.map +1 -1
  23. package/dist/esm/components/Table/SelectColumn.js +3 -2
  24. package/dist/esm/components/Table/SelectColumn.js.map +1 -1
  25. package/dist/esm/components/Table/Table.d.ts +7 -1
  26. package/dist/esm/components/Table/Table.d.ts.map +1 -1
  27. package/dist/esm/components/Table/Table.js +3 -3
  28. package/dist/esm/components/Table/Table.js.map +1 -1
  29. package/dist/esm/components/Table/TableTypes.d.ts +1 -0
  30. package/dist/esm/components/Table/TableTypes.d.ts.map +1 -1
  31. package/dist/esm/components/Table/Th.d.ts.map +1 -1
  32. package/dist/esm/components/Table/Th.js +2 -1
  33. package/dist/esm/components/Table/Th.js.map +1 -1
  34. package/dist/esm/components/Table/base/types.d.ts +2 -0
  35. package/dist/esm/components/Table/base/types.d.ts.map +1 -1
  36. package/dist/esm/components/Table/base/types.js.map +1 -1
  37. package/dist/esm/components/Table/utils/decorators/selectable.d.ts.map +1 -1
  38. package/dist/esm/components/Table/utils/decorators/selectable.js +2 -2
  39. package/dist/esm/components/Table/utils/decorators/selectable.js.map +1 -1
  40. package/dist/esm/components/Table/utils/decorators/sortable.js +2 -2
  41. package/dist/esm/components/Table/utils/decorators/sortable.js.map +1 -1
  42. package/dist/esm/components/Table/utils/decorators/treeRow.js +2 -2
  43. package/dist/esm/components/Table/utils/decorators/treeRow.js.map +1 -1
  44. package/dist/esm/demos/DashboardHeader.js +4 -4
  45. package/dist/esm/demos/DashboardHeader.js.map +1 -1
  46. package/dist/js/components/Table/CollapseColumn.js +2 -2
  47. package/dist/js/components/Table/CollapseColumn.js.map +1 -1
  48. package/dist/js/components/Table/EditColumn.js +2 -2
  49. package/dist/js/components/Table/EditColumn.js.map +1 -1
  50. package/dist/js/components/Table/EditableSelectInputCell.d.ts.map +1 -1
  51. package/dist/js/components/Table/EditableSelectInputCell.js.map +1 -1
  52. package/dist/js/components/Table/InnerScrollContainer.d.ts +3 -1
  53. package/dist/js/components/Table/InnerScrollContainer.d.ts.map +1 -1
  54. package/dist/js/components/Table/InnerScrollContainer.js +5 -4
  55. package/dist/js/components/Table/InnerScrollContainer.js.map +1 -1
  56. package/dist/js/components/Table/SelectColumn.d.ts +2 -0
  57. package/dist/js/components/Table/SelectColumn.d.ts.map +1 -1
  58. package/dist/js/components/Table/SelectColumn.js +3 -2
  59. package/dist/js/components/Table/SelectColumn.js.map +1 -1
  60. package/dist/js/components/Table/Table.d.ts +7 -1
  61. package/dist/js/components/Table/Table.d.ts.map +1 -1
  62. package/dist/js/components/Table/Table.js +3 -3
  63. package/dist/js/components/Table/Table.js.map +1 -1
  64. package/dist/js/components/Table/TableTypes.d.ts +1 -0
  65. package/dist/js/components/Table/TableTypes.d.ts.map +1 -1
  66. package/dist/js/components/Table/Th.d.ts.map +1 -1
  67. package/dist/js/components/Table/Th.js +2 -1
  68. package/dist/js/components/Table/Th.js.map +1 -1
  69. package/dist/js/components/Table/base/types.d.ts +2 -0
  70. package/dist/js/components/Table/base/types.d.ts.map +1 -1
  71. package/dist/js/components/Table/base/types.js.map +1 -1
  72. package/dist/js/components/Table/utils/decorators/selectable.d.ts.map +1 -1
  73. package/dist/js/components/Table/utils/decorators/selectable.js +2 -2
  74. package/dist/js/components/Table/utils/decorators/selectable.js.map +1 -1
  75. package/dist/js/components/Table/utils/decorators/sortable.js +2 -2
  76. package/dist/js/components/Table/utils/decorators/sortable.js.map +1 -1
  77. package/dist/js/components/Table/utils/decorators/treeRow.js +2 -2
  78. package/dist/js/components/Table/utils/decorators/treeRow.js.map +1 -1
  79. package/dist/js/demos/DashboardHeader.js +4 -4
  80. package/dist/js/demos/DashboardHeader.js.map +1 -1
  81. package/dist/umd/assets/{output-B4SR7-ii.css → output-N6l81wiC.css} +4293 -4093
  82. package/dist/umd/react-table.min.js +5 -5
  83. package/package.json +7 -7
  84. package/src/components/Table/CollapseColumn.tsx +2 -2
  85. package/src/components/Table/EditColumn.tsx +2 -2
  86. package/src/components/Table/EditableSelectInputCell.tsx +4 -2
  87. package/src/components/Table/InnerScrollContainer.tsx +9 -2
  88. package/src/components/Table/SelectColumn.tsx +9 -1
  89. package/src/components/Table/Table.tsx +13 -1
  90. package/src/components/Table/TableTypes.tsx +1 -0
  91. package/src/components/Table/Th.tsx +3 -3
  92. package/src/components/Table/__tests__/Table.test.tsx +66 -0
  93. package/src/components/Table/__tests__/Th.test.tsx +23 -0
  94. package/src/components/Table/__tests__/__snapshots__/RowWrapper.test.tsx.snap +2 -2
  95. package/src/components/Table/__tests__/__snapshots__/Table.test.tsx.snap +1 -1
  96. package/src/components/Table/__tests__/__snapshots__/Tr.test.tsx.snap +2 -2
  97. package/src/components/Table/base/types.tsx +2 -0
  98. package/src/components/Table/examples/Table.md +26 -6
  99. package/src/components/Table/examples/TableActions.tsx +4 -9
  100. package/src/components/Table/examples/TableBasic.tsx +5 -10
  101. package/src/components/Table/examples/TableEditable.tsx +2 -2
  102. package/src/components/Table/examples/TableMultipleStickyColumns.tsx +2 -2
  103. package/src/components/Table/examples/TableSelectableIndeterminate.tsx +128 -0
  104. package/src/components/Table/examples/TableStickyColumnsAndHeader.tsx +2 -2
  105. package/src/components/Table/examples/TableStickyHeaderDynamic.tsx +140 -0
  106. package/src/components/Table/utils/decorators/selectable.tsx +2 -1
  107. package/src/components/Table/utils/decorators/sortable.tsx +2 -2
  108. package/src/components/Table/utils/decorators/treeRow.tsx +2 -2
  109. package/src/demos/DashboardHeader.tsx +4 -4
  110. package/src/demos/Table.md +7 -8
  111. package/src/demos/examples/TableEmptyStateError.tsx +2 -2
  112. package/src/deprecated/components/Table/__tests__/__snapshots__/Table.test.tsx.snap +937 -469
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternfly/react-table",
3
- "version": "6.5.0-prerelease.8",
3
+ "version": "6.5.0-prerelease.80",
4
4
  "description": "This library provides a set of React table components for use with the PatternFly 4",
5
5
  "main": "dist/js/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -40,16 +40,16 @@
40
40
  "subpaths": "node ../../scripts/exportSubpaths.mjs --config subpaths.config.json"
41
41
  },
42
42
  "dependencies": {
43
- "@patternfly/react-core": "^6.5.0-prerelease.8",
44
- "@patternfly/react-icons": "^6.5.0-prerelease.3",
45
- "@patternfly/react-styles": "^6.5.0-prerelease.3",
46
- "@patternfly/react-tokens": "^6.5.0-prerelease.3",
47
- "lodash": "^4.17.21",
43
+ "@patternfly/react-core": "^6.5.0-prerelease.76",
44
+ "@patternfly/react-icons": "^6.5.0-prerelease.36",
45
+ "@patternfly/react-styles": "^6.5.0-prerelease.26",
46
+ "@patternfly/react-tokens": "^6.5.0-prerelease.25",
47
+ "lodash": "^4.18.1",
48
48
  "tslib": "^2.8.1"
49
49
  },
50
50
  "peerDependencies": {
51
51
  "react": "^17 || ^18 || ^19",
52
52
  "react-dom": "^17 || ^18 || ^19"
53
53
  },
54
- "gitHead": "a88ecfa753389be67ee88657914fc030440838f3"
54
+ "gitHead": "41fa345ea84fbf83dcefdd1dd46333be302f005d"
55
55
  }
@@ -1,5 +1,5 @@
1
1
  import { Fragment } from 'react';
2
- import AngleDownIcon from '@patternfly/react-icons/dist/esm/icons/angle-down-icon';
2
+ import RhMicronsCaretDownIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-caret-down-icon';
3
3
  import { css } from '@patternfly/react-styles';
4
4
  import { Button } from '@patternfly/react-core/dist/esm/components/Button';
5
5
  import styles from '@patternfly/react-styles/css/components/Table/table';
@@ -34,7 +34,7 @@ export const CollapseColumn: React.FunctionComponent<CollapseColumnProps> = ({
34
34
  aria-expanded={isOpen}
35
35
  icon={
36
36
  <div className={css(styles.tableToggleIcon)}>
37
- <AngleDownIcon />
37
+ <RhMicronsCaretDownIcon />
38
38
  </div>
39
39
  }
40
40
  />
@@ -2,7 +2,7 @@ import { Fragment } from 'react';
2
2
  import { Button } from '@patternfly/react-core/dist/esm/components/Button';
3
3
  import PencilAltIcon from '@patternfly/react-icons/dist/esm/icons/pencil-alt-icon';
4
4
  import CheckIcon from '@patternfly/react-icons/dist/esm/icons/check-icon';
5
- import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon';
5
+ import RhMicronsCloseIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-close-icon';
6
6
  import { OnRowEdit } from './TableTypes';
7
7
  import inlineStyles from '@patternfly/react-styles/css/components/InlineEdit/inline-edit';
8
8
  import { css } from '@patternfly/react-styles';
@@ -47,7 +47,7 @@ export const EditColumn: React.FunctionComponent<EditColumnProps> = ({
47
47
  {...props}
48
48
  onClick={(e) => onClick(e, 'cancel')}
49
49
  variant="plain"
50
- icon={<TimesIcon />}
50
+ icon={<RhMicronsCloseIcon />}
51
51
  />
52
52
  </div>
53
53
  </div>
@@ -6,8 +6,10 @@ import inlineStyles from '@patternfly/react-styles/css/components/InlineEdit/inl
6
6
  import formStyles from '@patternfly/react-styles/css/components/Form/form';
7
7
  import { EditableSelectInputProps } from './base/types';
8
8
 
9
- export interface IEditableSelectInputCell
10
- extends Omit<React.HTMLProps<HTMLElement | HTMLDivElement>, 'onSelect' | 'onToggle'> {
9
+ export interface IEditableSelectInputCell extends Omit<
10
+ React.HTMLProps<HTMLElement | HTMLDivElement>,
11
+ 'onSelect' | 'onToggle'
12
+ > {
11
13
  /** Row index of this select input cell */
12
14
  rowIndex: number;
13
15
  /** Cell index of this select input cell */
@@ -1,3 +1,4 @@
1
+ import { forwardRef } from 'react';
1
2
  import { css } from '@patternfly/react-styles';
2
3
  import styles from '@patternfly/react-styles/css/components/Table/table-scrollable';
3
4
 
@@ -6,16 +7,22 @@ export interface InnerScrollContainerProps extends React.HTMLProps<HTMLDivElemen
6
7
  children?: React.ReactNode;
7
8
  /** Additional classes added to the container */
8
9
  className?: string;
10
+ /** @hide Forwarded ref */
11
+ innerRef?: React.Ref<HTMLDivElement>;
9
12
  }
10
13
 
11
- export const InnerScrollContainer: React.FunctionComponent<InnerScrollContainerProps> = ({
14
+ const InnerScrollContainerBase: React.FunctionComponent<InnerScrollContainerProps> = ({
12
15
  children,
13
16
  className,
17
+ innerRef,
14
18
  ...props
15
19
  }: InnerScrollContainerProps) => (
16
- <div className={css(className, styles.scrollInnerWrapper)} {...props}>
20
+ <div ref={innerRef} className={css(className, styles.scrollInnerWrapper)} {...props}>
17
21
  {children}
18
22
  </div>
19
23
  );
20
24
 
25
+ export const InnerScrollContainer = forwardRef((props: InnerScrollContainerProps, ref: React.Ref<HTMLDivElement>) => (
26
+ <InnerScrollContainerBase innerRef={ref} {...props} />
27
+ ));
21
28
  InnerScrollContainer.displayName = 'InnerScrollContainer';
@@ -21,6 +21,8 @@ export interface SelectColumnProps {
21
21
  id?: string;
22
22
  /** name for the input element - required by Radio component */
23
23
  name?: string;
24
+ /** Whether the checkbox should be in an indeterminate state */
25
+ isIndeterminate?: boolean;
24
26
  }
25
27
 
26
28
  export const SelectColumn: React.FunctionComponent<SelectColumnProps> = ({
@@ -33,6 +35,7 @@ export const SelectColumn: React.FunctionComponent<SelectColumnProps> = ({
33
35
  tooltipProps,
34
36
  id,
35
37
  name,
38
+ isIndeterminate,
36
39
  ...props
37
40
  }: SelectColumnProps) => {
38
41
  const inputRef = createRef<any>();
@@ -48,10 +51,15 @@ export const SelectColumn: React.FunctionComponent<SelectColumnProps> = ({
48
51
  onChange: handleChange
49
52
  };
50
53
 
54
+ const checkboxProps = {
55
+ ...commonProps,
56
+ ...(isIndeterminate && { isChecked: null })
57
+ };
58
+
51
59
  const content = (
52
60
  <Fragment>
53
61
  {selectVariant === RowSelectVariant.checkbox ? (
54
- <Checkbox {...commonProps} />
62
+ <Checkbox {...checkboxProps} />
55
63
  ) : (
56
64
  <Radio {...commonProps} name={name} />
57
65
  )}
@@ -50,8 +50,14 @@ export interface TableProps extends React.HTMLProps<HTMLTableElement>, OUIAProps
50
50
  role?: string;
51
51
  /** @beta Flag indicating if the table should have plain styling with a transparent background */
52
52
  isPlain?: boolean;
53
- /** If set to true, the table header sticks to the top of its container */
53
+ /** @beta Flag indicating if the table should not have plain styling when in the glass theme */
54
+ isNoPlainOnGlass?: boolean;
55
+ /** If set to true, the table header sticks to the top of its container. This property applies both the sticky position and styling. */
54
56
  isStickyHeader?: boolean;
57
+ /** @beta Flag indicating the table header should have sticky positioning to the top of the parent InnerScrollContainer. */
58
+ isStickyHeaderBase?: boolean;
59
+ /** @beta Flag indicating the table header should have stuck styling, when the header is not at the top of the scroll container. */
60
+ isStickyHeaderStuck?: boolean;
55
61
  /** @hide Forwarded ref */
56
62
  innerRef?: React.RefObject<any>;
57
63
  /** Flag indicating table is a tree table */
@@ -96,7 +102,10 @@ const TableBase: React.FunctionComponent<TableProps> = ({
96
102
  variant,
97
103
  borders = true,
98
104
  isStickyHeader = false,
105
+ isStickyHeaderBase = false,
106
+ isStickyHeaderStuck = false,
99
107
  isPlain = false,
108
+ isNoPlainOnGlass = false,
100
109
  gridBreakPoint = TableGridBreakpoint.gridMd,
101
110
  'aria-label': ariaLabel,
102
111
  role = 'grid',
@@ -222,10 +231,13 @@ const TableBase: React.FunctionComponent<TableProps> = ({
222
231
  styles.modifiers[variant],
223
232
  !borders && styles.modifiers.noBorderRows,
224
233
  isStickyHeader && styles.modifiers.stickyHeader,
234
+ isStickyHeaderBase && styles.modifiers.stickyHeaderBase,
235
+ isStickyHeaderStuck && styles.modifiers.stickyHeaderStuck,
225
236
  isTreeTable && stylesTreeView.modifiers.treeView,
226
237
  isStriped && styles.modifiers.striped,
227
238
  isExpandable && styles.modifiers.expandable,
228
239
  isPlain && styles.modifiers.plain,
240
+ isNoPlainOnGlass && styles.modifiers.noPlainOnGlass,
229
241
  hasNoInset && stylesTreeView.modifiers.noInset,
230
242
  isNested && 'pf-m-nested',
231
243
  hasAnimations && styles.modifiers.animateExpand
@@ -107,6 +107,7 @@ export interface IColumn {
107
107
  allRowsSelected?: boolean;
108
108
  allRowsExpanded?: boolean;
109
109
  isHeaderSelectDisabled?: boolean;
110
+ isIndeterminate?: boolean;
110
111
  onFavorite?: OnFavorite;
111
112
  favoriteButtonProps?: ButtonProps;
112
113
  variant?: 'compact';
@@ -15,8 +15,7 @@ import cssStickyCellInlineStart from '@patternfly/react-tokens/dist/esm/c_table_
15
15
  import cssStickyCellInlineEnd from '@patternfly/react-tokens/dist/esm/c_table__sticky_cell_InsetInlineEnd';
16
16
 
17
17
  export interface ThProps
18
- extends BaseCellProps,
19
- Omit<React.HTMLProps<HTMLTableHeaderCellElement>, 'onSelect' | 'width'> {
18
+ extends BaseCellProps, Omit<React.HTMLProps<HTMLTableHeaderCellElement>, 'onSelect' | 'width'> {
20
19
  /**
21
20
  * The column header the cell corresponds to. Applicable when this component is used as a direct child to <Tr>.
22
21
  * This attribute replaces table header in mobile viewport. It is rendered by ::before pseudo element.
@@ -159,7 +158,8 @@ const ThBase: React.FunctionComponent<ThProps> = ({
159
158
  onSelect: select?.onSelect,
160
159
  selectVariant: 'checkbox',
161
160
  allRowsSelected: select.isSelected,
162
- isHeaderSelectDisabled: !!select.isHeaderSelectDisabled
161
+ isHeaderSelectDisabled: !!select.isHeaderSelectDisabled,
162
+ isIndeterminate: select?.isIndeterminate
163
163
  }
164
164
  },
165
165
  tooltip: tooltip as string,
@@ -156,3 +156,69 @@ test(`Renders with class ${styles.modifiers.plain} when isPlain is true`, () =>
156
156
 
157
157
  expect(screen.getByRole('grid', { name: 'Test table' })).toHaveClass(styles.modifiers.plain);
158
158
  });
159
+
160
+ test(`Does not render with class ${styles.modifiers.plain} when isPlain is not defined`, () => {
161
+ render(<Table aria-label="Test table" />);
162
+
163
+ expect(screen.getByRole('grid', { name: 'Test table' })).not.toHaveClass(styles.modifiers.plain);
164
+ });
165
+
166
+ test(`Does not render with class ${styles.modifiers.plain} when isPlain is false`, () => {
167
+ render(<Table isPlain={false} aria-label="Test table" />);
168
+
169
+ expect(screen.getByRole('grid', { name: 'Test table' })).not.toHaveClass(styles.modifiers.plain);
170
+ });
171
+
172
+ test(`Renders with class ${styles.modifiers.noPlainOnGlass} when isNoPlainOnGlass is true`, () => {
173
+ render(<Table isNoPlainOnGlass aria-label="Test table" />);
174
+
175
+ expect(screen.getByRole('grid', { name: 'Test table' })).toHaveClass(styles.modifiers.noPlainOnGlass);
176
+ });
177
+
178
+ test(`Does not render with class ${styles.modifiers.noPlainOnGlass} when isNoPlainOnGlass is undefined`, () => {
179
+ render(<Table aria-label="Test table" />);
180
+
181
+ expect(screen.getByRole('grid', { name: 'Test table' })).not.toHaveClass(styles.modifiers.noPlainOnGlass);
182
+ });
183
+
184
+ test(`Does not render with class ${styles.modifiers.noPlainOnGlass} when isNoPlainOnGlass is false`, () => {
185
+ render(<Table isNoPlainOnGlass={false} aria-label="Test table" />);
186
+
187
+ expect(screen.getByRole('grid', { name: 'Test table' })).not.toHaveClass(styles.modifiers.noPlainOnGlass);
188
+ });
189
+
190
+ test(`Renders with class ${styles.modifiers.stickyHeaderBase} when isStickyHeaderBase is true`, () => {
191
+ render(<Table isStickyHeaderBase aria-label="Test table" />);
192
+
193
+ expect(screen.getByRole('grid', { name: 'Test table' })).toHaveClass(styles.modifiers.stickyHeaderBase);
194
+ });
195
+
196
+ test(`Does not render with class ${styles.modifiers.stickyHeaderBase} when isStickyHeaderBase is false`, () => {
197
+ render(<Table isStickyHeaderBase={false} aria-label="Test table" />);
198
+
199
+ expect(screen.getByRole('grid', { name: 'Test table' })).not.toHaveClass(styles.modifiers.stickyHeaderBase);
200
+ });
201
+
202
+ test(`Does not render with class ${styles.modifiers.stickyHeaderBase} when isStickyHeaderBase is undefined`, () => {
203
+ render(<Table aria-label="Test table" />);
204
+
205
+ expect(screen.getByRole('grid', { name: 'Test table' })).not.toHaveClass(styles.modifiers.stickyHeaderBase);
206
+ });
207
+
208
+ test(`Renders with class ${styles.modifiers.stickyHeaderStuck} when isStickyHeaderStuck is true`, () => {
209
+ render(<Table isStickyHeaderStuck aria-label="Test table" />);
210
+
211
+ expect(screen.getByRole('grid', { name: 'Test table' })).toHaveClass(styles.modifiers.stickyHeaderStuck);
212
+ });
213
+
214
+ test(`Does not render with class ${styles.modifiers.stickyHeaderStuck} when isStickyHeaderStuck is false`, () => {
215
+ render(<Table isStickyHeaderStuck={false} aria-label="Test table" />);
216
+
217
+ expect(screen.getByRole('grid', { name: 'Test table' })).not.toHaveClass(styles.modifiers.stickyHeaderStuck);
218
+ });
219
+
220
+ test(`Does not render with class ${styles.modifiers.stickyHeaderStuck} when isStickyHeaderStuck is undefined`, () => {
221
+ render(<Table aria-label="Test table" />);
222
+
223
+ expect(screen.getByRole('grid', { name: 'Test table' })).not.toHaveClass(styles.modifiers.stickyHeaderStuck);
224
+ });
@@ -54,3 +54,26 @@ test('Additional content renders after children when additionalContent is passed
54
54
  expect(thChildren.item(0)?.textContent).toEqual('Test');
55
55
  expect(thChildren.item(1)?.textContent).toEqual('Extra');
56
56
  });
57
+
58
+ test('Renders checkbox without indeterminate state by default', () => {
59
+ render(<Th select={{ onSelect: jest.fn(), isSelected: false }} aria-label="Select all" />);
60
+
61
+ const checkbox = screen.getByRole('checkbox') as HTMLInputElement;
62
+ expect(checkbox).not.toBeChecked();
63
+ expect(checkbox.indeterminate).toBe(false);
64
+ });
65
+
66
+ test('Renders checkbox with indeterminate state when isIndeterminate is true', () => {
67
+ render(<Th select={{ onSelect: jest.fn(), isSelected: false, isIndeterminate: true }} aria-label="Select all" />);
68
+
69
+ const checkbox = screen.getByRole('checkbox') as HTMLInputElement;
70
+ expect(checkbox.indeterminate).toBe(true);
71
+ });
72
+
73
+ test('Renders checked checkbox when isSelected is true and isIndeterminate is false', () => {
74
+ render(<Th select={{ onSelect: jest.fn(), isSelected: true, isIndeterminate: false }} aria-label="Select all" />);
75
+
76
+ const checkbox = screen.getByRole('checkbox') as HTMLInputElement;
77
+ expect(checkbox).toBeChecked();
78
+ expect(checkbox.indeterminate).toBe(false);
79
+ });
@@ -6,7 +6,7 @@ exports[`RowWrapper renders correctly 1`] = `
6
6
  <tbody>
7
7
  <tr
8
8
  class="pf-v6-c-table__tr"
9
- data-ouia-component-id="OUIA-Generated-TableRow-1"
9
+ data-ouia-component-id="OUIA-Generated-TableRow-:r0:"
10
10
  data-ouia-component-type="PF6/TableRow"
11
11
  data-ouia-safe="true"
12
12
  />
@@ -21,7 +21,7 @@ exports[`RowWrapper renders expanded correctly 1`] = `
21
21
  <tbody>
22
22
  <tr
23
23
  class="pf-v6-c-table__tr pf-v6-c-table__expandable-row pf-m-expanded"
24
- data-ouia-component-id="OUIA-Generated-TableRow-2"
24
+ data-ouia-component-id="OUIA-Generated-TableRow-:r1:"
25
25
  data-ouia-component-type="PF6/TableRow"
26
26
  data-ouia-safe="true"
27
27
  />
@@ -4,7 +4,7 @@ exports[`Matches snapshot without children 1`] = `
4
4
  <DocumentFragment>
5
5
  <table
6
6
  class="pf-v6-c-table pf-m-grid-md"
7
- data-ouia-component-id="OUIA-Generated-Table-12"
7
+ data-ouia-component-id="OUIA-Generated-Table-:rb:"
8
8
  data-ouia-component-type="PF6/Table"
9
9
  data-ouia-safe="true"
10
10
  role="grid"
@@ -6,7 +6,7 @@ exports[`Matches snapshot with children 1`] = `
6
6
  <tbody>
7
7
  <tr
8
8
  class="pf-v6-c-table__tr"
9
- data-ouia-component-id="OUIA-Generated-TableRow-6"
9
+ data-ouia-component-id="OUIA-Generated-TableRow-:r5:"
10
10
  data-ouia-component-type="PF6/TableRow"
11
11
  data-ouia-safe="true"
12
12
  >
@@ -25,7 +25,7 @@ exports[`Matches snapshot without children 1`] = `
25
25
  <tbody>
26
26
  <tr
27
27
  class="pf-v6-c-table__tr"
28
- data-ouia-component-id="OUIA-Generated-TableRow-5"
28
+ data-ouia-component-id="OUIA-Generated-TableRow-:r4:"
29
29
  data-ouia-component-type="PF6/TableRow"
30
30
  data-ouia-safe="true"
31
31
  />
@@ -180,6 +180,8 @@ export interface ThSelectType {
180
180
  onSelect?: OnSelect;
181
181
  /** Whether the cell is selected */
182
182
  isSelected: boolean;
183
+ /** Whether the select checkbox should be in an indeterminate state (some items selected) */
184
+ isIndeterminate?: boolean;
183
185
  /** Flag indicating the select checkbox in the th is disabled */
184
186
  isHeaderSelectDisabled?: boolean;
185
187
  /** Whether to disable the selection */
@@ -41,7 +41,7 @@ The `Table` component takes an explicit and declarative approach, and its implem
41
41
 
42
42
  The documentation for the deprecated table implementation can be found under the [React deprecated](/components/table/react-deprecated) tab. It is configuration based and takes a less declarative and more implicit approach to laying out the table structure, such as the rows and cells within it.
43
43
 
44
- import { Fragment, isValidElement, useCallback, useEffect, useRef, useState } from 'react';
44
+ import { Fragment, isValidElement, useCallback, useEffect, useRef, useState, useLayoutEffect } from 'react';
45
45
  import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';
46
46
  import CodeBranchIcon from '@patternfly/react-icons/dist/esm/icons/code-branch-icon';
47
47
  import CodeIcon from '@patternfly/react-icons/dist/esm/icons/code-icon';
@@ -50,11 +50,11 @@ import LeafIcon from '@patternfly/react-icons/dist/esm/icons/leaf-icon';
50
50
  import FolderIcon from '@patternfly/react-icons/dist/esm/icons/folder-icon';
51
51
  import FolderOpenIcon from '@patternfly/react-icons/dist/esm/icons/folder-open-icon';
52
52
  import SortAmountDownIcon from '@patternfly/react-icons/dist/esm/icons/sort-amount-down-icon';
53
- import BlueprintIcon from '@patternfly/react-icons/dist/esm/icons/blueprint-icon';
53
+ import RhUiBlueprintIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-blueprint-icon';
54
54
  import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon';
55
55
  import PencilAltIcon from '@patternfly/react-icons/dist/esm/icons/pencil-alt-icon';
56
56
  import CheckIcon from '@patternfly/react-icons/dist/esm/icons/check-icon';
57
- import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon';
57
+ import RhMicronsCloseIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-close-icon';
58
58
 
59
59
  import { css } from '@patternfly/react-styles';
60
60
  import styles from '@patternfly/react-styles/css/components/Table/table';
@@ -78,10 +78,13 @@ Some general notes:
78
78
  ```ts file="TableBasic.tsx"
79
79
 
80
80
  ```
81
- ### Table Plain
82
- ``` file="TablePlain.tsx"
81
+
82
+ ### Plain
83
+
84
+ ```ts file="TablePlain.tsx"
83
85
 
84
86
  ```
87
+
85
88
  ### Custom row wrapper, header tooltips & popovers
86
89
 
87
90
  - If you add the `noWrap` prop to `Thead`, it won't wrap it if there is no space
@@ -155,6 +158,14 @@ checking checkboxes will check intermediate rows' checkboxes.
155
158
 
156
159
  ```
157
160
 
161
+ ### Selectable with indeterminate state
162
+
163
+ To indicate partial selection, use `isIndeterminate` on the header's `select` prop. When some (but not all) selectable rows are selected, the header checkbox will convey this information to assistive technologies and also display a dash instead of a checkmark.
164
+
165
+ ```ts file="TableSelectableIndeterminate.tsx"
166
+
167
+ ```
168
+
158
169
  ### Selectable radio input
159
170
 
160
171
  Similarly to the selectable example above, the radio buttons use the first column. The first header cell is empty, and each body row's first cell has radio button props.
@@ -324,7 +335,6 @@ To enable a tree table:
324
335
  - `checkAriaLabel` - (optional) accessible label for the checkbox
325
336
  - `showDetailsAriaLabel` - (optional) accessible label for the show row details button in the responsive view
326
337
  4. The first `Td` in each row will pass the following to the `treeRow` prop:
327
-
328
338
  - `onCollapse` - Callback when user expands/collapses a row to reveal/hide the row's children.
329
339
  - `onCheckChange` - (optional) Callback when user changes the checkbox on a row.
330
340
  - `onToggleRowDetails` - (optional) Callback when user shows/hides the row details in responsive view.
@@ -416,6 +426,16 @@ To prevent the default text wrapping behavior and allow horizontal scrolling, al
416
426
 
417
427
  ```
418
428
 
429
+ ### Dynamic sticky header
430
+
431
+ A sticky header may alternatively be implemented with two properties: `isStickyHeaderBase` and `isStickyHeaderStuck` - which allows separate control of the sticky position and sticky styling. `isStickyHeaderBase` should always be applied to make the header position sticky, and `isStickyHeaderStuck` may be applied dynamically to enable the sticky styling, such as when the sticky header is not at the top of the scroll parent as shown in the example.
432
+
433
+ `isStickyHeader` acts as if both properties are present and true when applied, and is useful when dynamic sticky styling is not necessary.
434
+
435
+ ```ts file="TableStickyHeaderDynamic.tsx"
436
+
437
+ ```
438
+
419
439
  ### Sticky columns and header
420
440
 
421
441
  To maintain proper sticky behavior across sticky columns and header, `Table` must be wrapped with `OuterScrollContainer` and `InnerScrollContainer`.
@@ -23,7 +23,7 @@ interface Repository {
23
23
  singleAction: string;
24
24
  }
25
25
 
26
- type ExampleType = 'defaultToggle' | 'customToggle';
26
+ type ExampleType = 'customToggle';
27
27
 
28
28
  export const TableActions: React.FunctionComponent = () => {
29
29
  // In real usage, this data would come from some external source like an API via props.
@@ -45,10 +45,11 @@ export const TableActions: React.FunctionComponent = () => {
45
45
  };
46
46
 
47
47
  // This state is just for the ToggleGroup in this example and isn't necessary for Table usage.
48
- const [exampleChoice, setExampleChoice] = useState<ExampleType>('defaultToggle');
48
+ const [exampleChoice, setExampleChoice] = useState<ExampleType | ''>('');
49
49
  const onExampleTypeChange: ToggleGroupItemProps['onChange'] = (event, _isSelected) => {
50
50
  const id = event.currentTarget.id;
51
- setExampleChoice(id as ExampleType);
51
+ // Allow toggling off if clicking the already selected item
52
+ setExampleChoice(exampleChoice === id ? '' : (id as ExampleType));
52
53
  };
53
54
 
54
55
  const customActionsToggle = (props: CustomActionsToggleProps) => (
@@ -95,12 +96,6 @@ export const TableActions: React.FunctionComponent = () => {
95
96
  return (
96
97
  <Fragment>
97
98
  <ToggleGroup aria-label="Default uses kebab toggle">
98
- <ToggleGroupItem
99
- text="Default actions toggle"
100
- buttonId="defaultToggle"
101
- isSelected={exampleChoice === 'defaultToggle'}
102
- onChange={onExampleTypeChange}
103
- />
104
99
  <ToggleGroupItem
105
100
  text="Custom actions toggle"
106
101
  buttonId="customToggle"
@@ -10,7 +10,7 @@ interface Repository {
10
10
  lastCommit: string;
11
11
  }
12
12
 
13
- type ExampleType = 'default' | 'compact' | 'compactBorderless';
13
+ type ExampleType = 'compact' | 'compactBorderless';
14
14
 
15
15
  export const TableBasic: React.FunctionComponent = () => {
16
16
  // In real usage, this data would come from some external source like an API via props.
@@ -29,21 +29,16 @@ export const TableBasic: React.FunctionComponent = () => {
29
29
  };
30
30
 
31
31
  // This state is just for the ToggleGroup in this example and isn't necessary for Table usage.
32
- const [exampleChoice, setExampleChoice] = useState<ExampleType>('default');
32
+ const [exampleChoice, setExampleChoice] = useState<ExampleType | ''>('');
33
33
  const onExampleTypeChange: ToggleGroupItemProps['onChange'] = (event, _isSelected) => {
34
34
  const id = event.currentTarget.id;
35
- setExampleChoice(id as ExampleType);
35
+ // Allow toggling off if clicking the already selected item
36
+ setExampleChoice(exampleChoice === id ? '' : (id as ExampleType));
36
37
  };
37
38
 
38
39
  return (
39
40
  <Fragment>
40
41
  <ToggleGroup aria-label="Default with single selectable">
41
- <ToggleGroupItem
42
- text="Default"
43
- buttonId="default"
44
- isSelected={exampleChoice === 'default'}
45
- onChange={onExampleTypeChange}
46
- />
47
42
  <ToggleGroupItem
48
43
  text="Compact"
49
44
  buttonId="compact"
@@ -59,7 +54,7 @@ export const TableBasic: React.FunctionComponent = () => {
59
54
  </ToggleGroup>
60
55
  <Table
61
56
  aria-label="Simple table"
62
- variant={exampleChoice !== 'default' ? 'compact' : undefined}
57
+ variant={exampleChoice === 'compact' || exampleChoice === 'compactBorderless' ? 'compact' : undefined}
63
58
  borders={exampleChoice !== 'compactBorderless'}
64
59
  >
65
60
  <Caption>Simple table using composable components</Caption>
@@ -3,7 +3,7 @@ import { Table, Thead, Tr, Th, Tbody, Td } from '@patternfly/react-table';
3
3
  import { Button, Checkbox, Radio, TextInput, KeyTypes, getUniqueId } from '@patternfly/react-core';
4
4
  import PencilAltIcon from '@patternfly/react-icons/dist/esm/icons/pencil-alt-icon';
5
5
  import CheckIcon from '@patternfly/react-icons/dist/esm/icons/check-icon';
6
- import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon';
6
+ import RhMicronsCloseIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-close-icon';
7
7
  import inlineEditStyles from '@patternfly/react-styles/css/components/InlineEdit/inline-edit';
8
8
  import { css } from '@patternfly/react-styles';
9
9
 
@@ -60,7 +60,7 @@ const EditButtonsCell: React.FunctionComponent<EditButtonsCellProps> = ({
60
60
  onKeyDown={(event) => onKeyDown(event, 'stopEditing')}
61
61
  variant="plain"
62
62
  >
63
- <TimesIcon />
63
+ <RhMicronsCloseIcon />
64
64
  </Button>
65
65
  </div>
66
66
  </Td>
@@ -1,6 +1,6 @@
1
1
  import { useState } from 'react';
2
2
  import { Table, Thead, Tr, Th, Tbody, Td, InnerScrollContainer, ThProps } from '@patternfly/react-table';
3
- import BlueprintIcon from '@patternfly/react-icons/dist/esm/icons/blueprint-icon';
3
+ import RhUiBlueprintIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-blueprint-icon';
4
4
 
5
5
  interface Fact {
6
6
  name: string;
@@ -120,7 +120,7 @@ export const TableMultipleStickyColumns: React.FunctionComponent = () => {
120
120
  {fact.name}
121
121
  </Th>
122
122
  <Th isStickyColumn stickyMinWidth="120px" stickyLeftOffset="120px" modifier="truncate" hasRightBorder>
123
- <BlueprintIcon />
123
+ <RhUiBlueprintIcon />
124
124
  {` ${fact.state}`}
125
125
  </Th>
126
126
  <Td modifier="nowrap" dataLabel={columnNames.header3}>