@patternfly/react-table 6.3.0-prerelease.9 → 6.3.1-prerelease.0

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 (82) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/components/package.json +1 -1
  3. package/deprecated/package.json +1 -1
  4. package/dist/dynamic/components/Table/package.json +1 -1
  5. package/dist/dynamic/components/Table/utils/decorators/package.json +1 -1
  6. package/dist/dynamic/components/Table/utils/package.json +1 -1
  7. package/dist/dynamic/deprecated/components/Table/base/package.json +1 -1
  8. package/dist/dynamic/deprecated/components/Table/package.json +1 -1
  9. package/dist/dynamic/deprecated/components/package.json +1 -1
  10. package/dist/esm/components/Table/ExpandableRowContent.d.ts +5 -0
  11. package/dist/esm/components/Table/ExpandableRowContent.d.ts.map +1 -1
  12. package/dist/esm/components/Table/ExpandableRowContent.js +2 -2
  13. package/dist/esm/components/Table/ExpandableRowContent.js.map +1 -1
  14. package/dist/esm/components/Table/Table.d.ts +6 -1
  15. package/dist/esm/components/Table/Table.d.ts.map +1 -1
  16. package/dist/esm/components/Table/Table.js +5 -4
  17. package/dist/esm/components/Table/Table.js.map +1 -1
  18. package/dist/esm/components/Table/Td.d.ts +2 -0
  19. package/dist/esm/components/Table/Td.d.ts.map +1 -1
  20. package/dist/esm/components/Table/Td.js +25 -4
  21. package/dist/esm/components/Table/Td.js.map +1 -1
  22. package/dist/esm/components/Table/Tr.d.ts +5 -1
  23. package/dist/esm/components/Table/Tr.d.ts.map +1 -1
  24. package/dist/esm/components/Table/Tr.js +3 -3
  25. package/dist/esm/components/Table/Tr.js.map +1 -1
  26. package/dist/esm/demos/DashboardHeader.d.ts.map +1 -1
  27. package/dist/esm/demos/DashboardHeader.js +1 -2
  28. package/dist/esm/demos/DashboardHeader.js.map +1 -1
  29. package/dist/esm/demos/sampleData.d.ts.map +1 -1
  30. package/dist/esm/demos/sampleData.js +359 -360
  31. package/dist/esm/demos/sampleData.js.map +1 -1
  32. package/dist/js/components/Table/ExpandableRowContent.d.ts +5 -0
  33. package/dist/js/components/Table/ExpandableRowContent.d.ts.map +1 -1
  34. package/dist/js/components/Table/ExpandableRowContent.js +2 -2
  35. package/dist/js/components/Table/ExpandableRowContent.js.map +1 -1
  36. package/dist/js/components/Table/Table.d.ts +6 -1
  37. package/dist/js/components/Table/Table.d.ts.map +1 -1
  38. package/dist/js/components/Table/Table.js +5 -4
  39. package/dist/js/components/Table/Table.js.map +1 -1
  40. package/dist/js/components/Table/Td.d.ts +2 -0
  41. package/dist/js/components/Table/Td.d.ts.map +1 -1
  42. package/dist/js/components/Table/Td.js +24 -3
  43. package/dist/js/components/Table/Td.js.map +1 -1
  44. package/dist/js/components/Table/Tr.d.ts +5 -1
  45. package/dist/js/components/Table/Tr.d.ts.map +1 -1
  46. package/dist/js/components/Table/Tr.js +3 -3
  47. package/dist/js/components/Table/Tr.js.map +1 -1
  48. package/dist/js/demos/DashboardHeader.d.ts.map +1 -1
  49. package/dist/js/demos/DashboardHeader.js +1 -2
  50. package/dist/js/demos/DashboardHeader.js.map +1 -1
  51. package/dist/js/demos/sampleData.d.ts.map +1 -1
  52. package/dist/js/demos/sampleData.js +359 -360
  53. package/dist/js/demos/sampleData.js.map +1 -1
  54. package/dist/umd/assets/{output-PMQiOdP-.css → output-CKjCu3-7.css} +3852 -3434
  55. package/dist/umd/react-table.min.js +2 -2
  56. package/package.json +6 -6
  57. package/src/components/Table/ExpandableRowContent.tsx +7 -1
  58. package/src/components/Table/Table.tsx +12 -4
  59. package/src/components/Table/Td.tsx +41 -2
  60. package/src/components/Table/Tr.tsx +9 -3
  61. package/src/components/Table/__tests__/ExpandableRowContent.test.tsx +39 -0
  62. package/src/components/Table/__tests__/Table.test.tsx +62 -0
  63. package/src/components/Table/__tests__/Td.test.tsx +87 -0
  64. package/src/components/Table/__tests__/Tr.test.tsx +79 -0
  65. package/src/components/Table/__tests__/__snapshots__/ExpandableRowContent.test.tsx.snap +11 -0
  66. package/src/components/Table/__tests__/__snapshots__/Table.test.tsx.snap +13 -0
  67. package/src/components/Table/__tests__/__snapshots__/Td.test.tsx.snap +33 -0
  68. package/src/components/Table/__tests__/__snapshots__/Tr.test.tsx.snap +35 -0
  69. package/src/components/Table/examples/Table.md +12 -6
  70. package/src/components/Table/examples/TableActions.tsx +1 -1
  71. package/src/components/Table/examples/TableCompoundExpandable.tsx +23 -21
  72. package/src/components/Table/examples/TableExpandable.tsx +7 -2
  73. package/src/components/Table/examples/TableMisc.tsx +0 -1
  74. package/src/components/Table/examples/TableNestedExpandable.tsx +2 -2
  75. package/src/components/Table/examples/TableNestedTableExpandable.tsx +2 -2
  76. package/src/components/Table/examples/TableStripedExpandable.tsx +8 -2
  77. package/src/demos/DashboardHeader.tsx +2 -5
  78. package/src/demos/examples/TableCompoundExpansion.tsx +87 -84
  79. package/src/demos/examples/TableExpandCollapseAll.tsx +2 -2
  80. package/src/demos/examples/TableSortableResponsive.tsx +5 -5
  81. package/src/demos/sampleData.tsx +359 -361
  82. package/src/deprecated/components/Table/examples/LegacyTableMisc.tsx +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternfly/react-table",
3
- "version": "6.3.0-prerelease.9",
3
+ "version": "6.3.1-prerelease.0",
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,10 +40,10 @@
40
40
  "subpaths": "node ../../scripts/exportSubpaths.mjs --config subpaths.config.json"
41
41
  },
42
42
  "dependencies": {
43
- "@patternfly/react-core": "^6.3.0-prerelease.9",
44
- "@patternfly/react-icons": "^6.3.0-prerelease.1",
45
- "@patternfly/react-styles": "^6.3.0-prerelease.1",
46
- "@patternfly/react-tokens": "^6.3.0-prerelease.1",
43
+ "@patternfly/react-core": "^6.3.1-prerelease.0",
44
+ "@patternfly/react-icons": "^6.3.0",
45
+ "@patternfly/react-styles": "^6.3.0",
46
+ "@patternfly/react-tokens": "^6.3.0",
47
47
  "lodash": "^4.17.21",
48
48
  "tslib": "^2.8.1"
49
49
  },
@@ -51,5 +51,5 @@
51
51
  "react": "^17 || ^18 || ^19",
52
52
  "react-dom": "^17 || ^18 || ^19"
53
53
  },
54
- "gitHead": "6e99233806b7116f6f785411ba92f8ce28411a58"
54
+ "gitHead": "999dd945fd4f8ec281d9015586ac773833f16217"
55
55
  }
@@ -2,14 +2,20 @@ import { css } from '@patternfly/react-styles';
2
2
  import styles from '@patternfly/react-styles/css/components/Table/table';
3
3
 
4
4
  interface ExpandableRowContentProps {
5
+ /** Content rendered inside the expandable row. */
5
6
  children?: React.ReactNode;
7
+ /** Flag indicating whether the expandable row content has no background. This should be passed in when
8
+ * the parent Td is passed the noPadding prop.
9
+ */
10
+ hasNoBackground?: boolean;
6
11
  }
7
12
 
8
13
  export const ExpandableRowContent: React.FunctionComponent<ExpandableRowContentProps> = ({
9
14
  children = null as React.ReactNode,
15
+ hasNoBackground,
10
16
  ...props
11
17
  }: ExpandableRowContentProps) => (
12
- <div {...props} className={css(styles.tableExpandableRowContent)}>
18
+ <div {...props} className={css(styles.tableExpandableRowContent, hasNoBackground && styles.modifiers.noBackground)}>
13
19
  {children}
14
20
  </div>
15
21
  );
@@ -57,8 +57,12 @@ export interface TableProps extends React.HTMLProps<HTMLTableElement>, OUIAProps
57
57
  isNested?: boolean;
58
58
  /** Flag indicating this table should be striped. This property works best for a single <tbody> table. Striping may also be done manually by applying this property to Tbody and Tr components. */
59
59
  isStriped?: boolean;
60
- /** Flag indicating this table contains expandable rows to maintain proper striping */
60
+ /** Flag indicating this table contains expandable rows. */
61
61
  isExpandable?: boolean;
62
+ /** @beta Flag indicating whether expandable rows within the table have animations. Expandable rows cannot be dynamically rendered. This prop
63
+ * will be removed in the next breaking change, with the default behavior becoming animations always being enabled.
64
+ */
65
+ hasAnimations?: boolean;
62
66
  /** Flag indicating this table's rows will not have the inset typically reserved for expanding/collapsing rows in a tree table. Intended for use on tree tables with no visible rows with children. */
63
67
  hasNoInset?: boolean;
64
68
  /** Collection of column spans for nested headers. Deprecated: see https://github.com/patternfly/patternfly/issues/4584 */
@@ -73,10 +77,12 @@ export interface TableProps extends React.HTMLProps<HTMLTableElement>, OUIAProps
73
77
 
74
78
  interface TableContextProps {
75
79
  registerSelectableRow?: () => void;
80
+ hasAnimations?: boolean;
76
81
  }
77
82
 
78
83
  export const TableContext = createContext<TableContextProps>({
79
- registerSelectableRow: () => {}
84
+ registerSelectableRow: () => {},
85
+ hasAnimations: false
80
86
  });
81
87
 
82
88
  const TableBase: React.FunctionComponent<TableProps> = ({
@@ -95,6 +101,7 @@ const TableBase: React.FunctionComponent<TableProps> = ({
95
101
  isNested = false,
96
102
  isStriped = false,
97
103
  isExpandable = false,
104
+ hasAnimations = false,
98
105
  hasNoInset = false,
99
106
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
100
107
  nestedHeaderColumnSpans,
@@ -197,7 +204,7 @@ const TableBase: React.FunctionComponent<TableProps> = ({
197
204
  };
198
205
 
199
206
  return (
200
- <TableContext.Provider value={{ registerSelectableRow }}>
207
+ <TableContext.Provider value={{ registerSelectableRow, hasAnimations }}>
201
208
  <table
202
209
  aria-label={ariaLabel}
203
210
  role={role}
@@ -212,7 +219,8 @@ const TableBase: React.FunctionComponent<TableProps> = ({
212
219
  isStriped && styles.modifiers.striped,
213
220
  isExpandable && styles.modifiers.expandable,
214
221
  hasNoInset && stylesTreeView.modifiers.noInset,
215
- isNested && 'pf-m-nested'
222
+ isNested && 'pf-m-nested',
223
+ hasAnimations && styles.modifiers.animateExpand
216
224
  )}
217
225
  ref={tableRef}
218
226
  {...(isTreeTable && { role: 'treegrid' })}
@@ -1,4 +1,4 @@
1
- import { createRef, forwardRef, useEffect, useState } from 'react';
1
+ import { createRef, forwardRef, useEffect, useState, useContext } from 'react';
2
2
  import { css } from '@patternfly/react-styles';
3
3
  import styles from '@patternfly/react-styles/css/components/Table/table';
4
4
  import scrollStyles from '@patternfly/react-styles/css/components/Table/table-scrollable';
@@ -14,6 +14,7 @@ import {
14
14
  classNames,
15
15
  favoritable
16
16
  } from './utils';
17
+ import { IRowData, IExtraData } from './TableTypes';
17
18
  import { draggable } from './utils/decorators/draggable';
18
19
  import { treeRow } from './utils';
19
20
  import { mergeProps } from './base/merge-props';
@@ -29,6 +30,7 @@ import {
29
30
  TdSelectType,
30
31
  TdTreeRowType
31
32
  } from './base/types';
33
+ import { TableContext } from './Table';
32
34
  import cssStickyCellMinWidth from '@patternfly/react-tokens/dist/esm/c_table__sticky_cell_MinWidth';
33
35
  import cssStickyCellInlineStart from '@patternfly/react-tokens/dist/esm/c_table__sticky_cell_InsetInlineStart';
34
36
  import cssStickyCellInlineEnd from '@patternfly/react-tokens/dist/esm/c_table__sticky_cell_InsetInlineEnd';
@@ -43,6 +45,8 @@ export interface TdProps extends BaseCellProps, Omit<React.HTMLProps<HTMLTableDa
43
45
  select?: TdSelectType;
44
46
  /** Turns the cell into an actions cell. Recommended to use an ActionsColumn component as a child of the Td rather than this prop. */
45
47
  actions?: TdActionsType;
48
+ /** Indicates the cell contains an interactive element and prevents that element's padding from increasing row height. Recommended when other cells in the same row contains text. */
49
+ hasAction?: boolean;
46
50
  /** Turns the cell into an expansion toggle and determines if the corresponding expansion row is open */
47
51
  expand?: TdExpandType;
48
52
  /** Turns the cell into a compound expansion toggle */
@@ -84,6 +88,7 @@ const TdBase: React.FunctionComponent<TdProps> = ({
84
88
  children,
85
89
  className,
86
90
  isActionCell = false,
91
+ hasAction = false,
87
92
  component = 'td',
88
93
  dataLabel,
89
94
  textCenter = false,
@@ -193,6 +198,39 @@ const TdBase: React.FunctionComponent<TdProps> = ({
193
198
  }
194
199
  })
195
200
  : null;
201
+
202
+ const { hasAnimations } = useContext(TableContext);
203
+ const updateAnimationClass = () => {
204
+ const ancestorControlRow = (cellRef as React.RefObject<HTMLElement | null>)?.current?.closest(
205
+ `.${styles.tableTr}.${styles.tableControlRow}`
206
+ );
207
+ const isControlRowExpanded = ancestorControlRow.classList.contains(styles.modifiers.expanded);
208
+ if (!isControlRowExpanded) {
209
+ return;
210
+ }
211
+
212
+ const isCurrentCellExpanded = (cellRef as React.RefObject<HTMLElement | null>)?.current?.classList.contains(
213
+ styles.modifiers.expanded
214
+ );
215
+ if (isCurrentCellExpanded) {
216
+ ancestorControlRow.classList.remove(styles.modifiers.noAnimateExpand);
217
+ } else {
218
+ ancestorControlRow.classList.add(styles.modifiers.noAnimateExpand);
219
+ }
220
+ };
221
+
222
+ const internalCompoundOnToggle = (
223
+ event: React.MouseEvent,
224
+ rowIndex: number,
225
+ colIndex: number,
226
+ isOpen: boolean,
227
+ rowData: IRowData,
228
+ extraData: IExtraData
229
+ ) => {
230
+ hasAnimations && updateAnimationClass();
231
+ compoundExpandProp?.onToggle(event, rowIndex, colIndex, isOpen, rowData, extraData);
232
+ };
233
+
196
234
  const compoundParams =
197
235
  compoundExpandProp !== null
198
236
  ? compoundExpand(
@@ -207,7 +245,7 @@ const TdBase: React.FunctionComponent<TdProps> = ({
207
245
  columnIndex: compoundExpandProp?.columnIndex,
208
246
  column: {
209
247
  extraParams: {
210
- onExpand: compoundExpandProp?.onToggle,
248
+ onExpand: internalCompoundOnToggle,
211
249
  expandId: compoundExpandProp?.expandId
212
250
  }
213
251
  }
@@ -279,6 +317,7 @@ const TdBase: React.FunctionComponent<TdProps> = ({
279
317
  styles.tableTd,
280
318
  className,
281
319
  isActionCell && styles.tableAction,
320
+ hasAction && styles.modifiers.action,
282
321
  textCenter && styles.modifiers.center,
283
322
  noPadding && styles.modifiers.noPadding,
284
323
  isStickyColumn && scrollStyles.tableStickyCell,
@@ -14,10 +14,14 @@ export interface TrProps extends Omit<React.HTMLProps<HTMLTableRowElement>, 'onR
14
14
  innerRef?: React.Ref<any>;
15
15
  /** Flag indicating the Tr is hidden */
16
16
  isHidden?: boolean;
17
- /** Only applicable to Tr within the Tbody: Makes the row expandable and determines if it's expanded or not.
17
+ /** Flag indicating whether an "expandable" Tr is expanded or not. Only applicable to a Tr within a Tbody.
18
18
  * To prevent column widths from responding automatically when expandable rows are toggled, the width prop must also be passed into either the th or td component
19
19
  */
20
20
  isExpanded?: boolean;
21
+ /** Flag indicating that the "control row" Tr has an expandable sibling Tr that is expanded or not. Only applicable to
22
+ * a Tr within a Tbody, and should have the same value as an expandable Tr's isExpanded prop.
23
+ */
24
+ isContentExpanded?: boolean;
21
25
  /** Only applicable to Tr within the Tbody: Whether the row is editable */
22
26
  isEditable?: boolean;
23
27
  /** Flag which adds hover styles for the clickable table row */
@@ -46,6 +50,7 @@ const TrBase: React.FunctionComponent<TrProps> = ({
46
50
  children,
47
51
  className,
48
52
  isExpanded,
53
+ isContentExpanded,
49
54
  isEditable,
50
55
  isHidden = false,
51
56
  isClickable = false,
@@ -77,7 +82,7 @@ const TrBase: React.FunctionComponent<TrProps> = ({
77
82
 
78
83
  const rowIsHidden = isHidden || (isExpanded !== undefined && !isExpanded);
79
84
 
80
- const { registerSelectableRow } = useContext(TableContext);
85
+ const { registerSelectableRow, hasAnimations } = useContext(TableContext);
81
86
 
82
87
  useEffect(() => {
83
88
  if (isSelectable && !rowIsHidden) {
@@ -97,7 +102,7 @@ const TrBase: React.FunctionComponent<TrProps> = ({
97
102
  styles.tableTr,
98
103
  className,
99
104
  isExpanded !== undefined && styles.tableExpandableRow,
100
- isExpanded && styles.modifiers.expanded,
105
+ (isExpanded || isContentExpanded) && styles.modifiers.expanded,
101
106
  isEditable && inlineStyles.modifiers.inlineEditable,
102
107
  isClickable && styles.modifiers.clickable,
103
108
  isRowSelected && styles.modifiers.selected,
@@ -110,6 +115,7 @@ const TrBase: React.FunctionComponent<TrProps> = ({
110
115
  {...(isClickable && { tabIndex: 0 })}
111
116
  aria-label={ariaLabel}
112
117
  ref={innerRef}
118
+ {...(hasAnimations && rowIsHidden && { inert: '' })}
113
119
  {...(onRowClick && { onClick: onRowClick, onKeyDown })}
114
120
  {...ouiaProps}
115
121
  {...props}
@@ -0,0 +1,39 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import { ExpandableRowContent } from '../ExpandableRowContent';
3
+ import styles from '@patternfly/react-styles/css/components/Table/table';
4
+
5
+ test('Renders without children', () => {
6
+ render(<ExpandableRowContent data-testid="row-id" />);
7
+
8
+ expect(screen.getByTestId('row-id')).toBeInTheDocument();
9
+ });
10
+
11
+ test('Renders with children', () => {
12
+ render(<ExpandableRowContent>Row content</ExpandableRowContent>);
13
+
14
+ expect(screen.getByText('Row content')).toBeVisible();
15
+ });
16
+
17
+ test(`Renders only with class ${styles.tableExpandableRowContent} by default`, () => {
18
+ render(<ExpandableRowContent>Row content</ExpandableRowContent>);
19
+
20
+ expect(screen.getByText('Row content')).toHaveClass(styles.tableExpandableRowContent, { exact: true });
21
+ });
22
+
23
+ test(`Renders with class ${styles.modifiers.noBackground} when hasNoBackground is true`, () => {
24
+ render(<ExpandableRowContent hasNoBackground>Row content</ExpandableRowContent>);
25
+
26
+ expect(screen.getByText('Row content')).toHaveClass(styles.modifiers.noBackground);
27
+ });
28
+
29
+ test(`Spreads additional props`, () => {
30
+ render(<ExpandableRowContent data-custom="true">Row content</ExpandableRowContent>);
31
+
32
+ expect(screen.getByText('Row content')).toHaveAttribute('data-custom', 'true');
33
+ });
34
+
35
+ test('Matches snapshot', () => {
36
+ const { asFragment } = render(<ExpandableRowContent>Row content</ExpandableRowContent>);
37
+
38
+ expect(asFragment()).toMatchSnapshot();
39
+ });
@@ -0,0 +1,62 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import { Table } from '../Table';
3
+ import styles from '@patternfly/react-styles/css/components/Table/table';
4
+
5
+ test('Renders without children', () => {
6
+ render(<Table aria-label="Test table" />);
7
+
8
+ expect(screen.getByRole('grid', { name: 'Test table' })).toBeInTheDocument();
9
+ });
10
+
11
+ test('Renders with children', () => {
12
+ render(
13
+ <Table aria-label="Test table">
14
+ <caption>Table caption</caption>
15
+ </Table>
16
+ );
17
+
18
+ expect(screen.getByRole('grid', { name: 'Test table' })).toHaveTextContent('Table caption');
19
+ });
20
+
21
+ test('Renders with role="treegrid" when isTreeTable is true', () => {
22
+ render(<Table isTreeTable aria-label="Test table" />);
23
+
24
+ expect(screen.getByRole('treegrid', { name: 'Test table' })).toBeInTheDocument();
25
+ });
26
+
27
+ test(`Renders with class ${styles.table} by default`, () => {
28
+ render(<Table aria-label="Test table" />);
29
+
30
+ expect(screen.getByRole('grid', { name: 'Test table' })).toHaveClass(styles.table);
31
+ });
32
+
33
+ test(`Renders with a pf-m-grid class by default`, () => {
34
+ render(<Table aria-label="Test table" />);
35
+
36
+ expect(screen.getByRole('grid', { name: 'Test table' })).toHaveClass(/^pf-m-grid/);
37
+ });
38
+
39
+ test(`Renders with a pf-m-tree-view-grid class when isTreeTable is true`, () => {
40
+ render(<Table isTreeTable aria-label="Test table" />);
41
+
42
+ expect(screen.getByRole('treegrid', { name: 'Test table' })).not.toHaveClass(/^pf-m-grid/);
43
+ expect(screen.getByRole('treegrid', { name: 'Test table' })).toHaveClass(/^pf-m-tree-view-grid/);
44
+ });
45
+
46
+ test(`Does not render with class ${styles.modifiers.animateExpand} by default`, () => {
47
+ render(<Table aria-label="Test table" />);
48
+
49
+ expect(screen.getByRole('grid', { name: 'Test table' })).not.toHaveClass(styles.modifiers.animateExpand);
50
+ });
51
+
52
+ test(`Renders with class ${styles.modifiers.animateExpand} hasAnimations is true`, () => {
53
+ render(<Table hasAnimations aria-label="Test table" />);
54
+
55
+ expect(screen.getByRole('grid', { name: 'Test table' })).toHaveClass(styles.modifiers.animateExpand);
56
+ });
57
+
58
+ test('Matches snapshot without children', () => {
59
+ const { asFragment } = render(<Table />);
60
+
61
+ expect(asFragment()).toMatchSnapshot();
62
+ });
@@ -0,0 +1,87 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import styles from '@patternfly/react-styles/css/components/Table/table';
3
+ import { Td } from '../Td';
4
+
5
+ test('Renders without children', () => {
6
+ render(
7
+ <table>
8
+ <tbody>
9
+ <tr>
10
+ <Td />
11
+ </tr>
12
+ </tbody>
13
+ </table>
14
+ );
15
+
16
+ expect(screen.getByRole('cell')).toBeInTheDocument();
17
+ });
18
+
19
+ test('Renders with children', () => {
20
+ render(
21
+ <table>
22
+ <tbody>
23
+ <tr>
24
+ <Td>Cell content</Td>
25
+ </tr>
26
+ </tbody>
27
+ </table>
28
+ );
29
+
30
+ expect(screen.getByRole('cell')).toHaveTextContent('Cell content');
31
+ });
32
+
33
+ test(`Applies ${styles.modifiers.action} when hasAction is true`, () => {
34
+ render(
35
+ <table>
36
+ <tbody>
37
+ <tr>
38
+ <Td hasAction>Cell with action</Td>
39
+ </tr>
40
+ </tbody>
41
+ </table>
42
+ );
43
+
44
+ expect(screen.getByRole('cell')).toHaveClass('pf-m-action');
45
+ });
46
+
47
+ test(`Does not apply ${styles.modifiers.action} when hasAction is false`, () => {
48
+ render(
49
+ <table>
50
+ <tbody>
51
+ <tr>
52
+ <Td hasAction={false}>Cell without action</Td>
53
+ </tr>
54
+ </tbody>
55
+ </table>
56
+ );
57
+
58
+ expect(screen.getByRole('cell')).not.toHaveClass('pf-m-action');
59
+ });
60
+
61
+ test('Matches snapshot without children', () => {
62
+ const { asFragment } = render(
63
+ <table>
64
+ <tbody>
65
+ <tr>
66
+ <Td />
67
+ </tr>
68
+ </tbody>
69
+ </table>
70
+ );
71
+
72
+ expect(asFragment()).toMatchSnapshot();
73
+ });
74
+
75
+ test('Matches snapshot with children', () => {
76
+ const { asFragment } = render(
77
+ <table>
78
+ <tbody>
79
+ <tr>
80
+ <Td>Cell content</Td>
81
+ </tr>
82
+ </tbody>
83
+ </table>
84
+ );
85
+
86
+ expect(asFragment()).toMatchSnapshot();
87
+ });
@@ -0,0 +1,79 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import { Tr } from '../Tr';
3
+ import styles from '@patternfly/react-styles/css/components/Table/table';
4
+
5
+ test('Renders without children', () => {
6
+ render(
7
+ <table>
8
+ <tbody>
9
+ <Tr />
10
+ </tbody>
11
+ </table>
12
+ );
13
+
14
+ expect(screen.getByRole('row')).toBeInTheDocument();
15
+ });
16
+
17
+ test('Renders with children', () => {
18
+ render(
19
+ <table>
20
+ <tbody>
21
+ <Tr>
22
+ <td>Row content</td>
23
+ </Tr>
24
+ </tbody>
25
+ </table>
26
+ );
27
+
28
+ expect(screen.getByRole('row')).toHaveTextContent('Row content');
29
+ });
30
+
31
+ test(`Does not render as hidden by default`, () => {
32
+ render(
33
+ <table>
34
+ <tbody>
35
+ <Tr />
36
+ </tbody>
37
+ </table>
38
+ );
39
+
40
+ expect(screen.getByRole('row')).not.toHaveAttribute('hidden');
41
+ });
42
+
43
+ test(`Renders as hidden when isHidden is true`, () => {
44
+ render(
45
+ <table>
46
+ <tbody>
47
+ <Tr isHidden />
48
+ </tbody>
49
+ </table>
50
+ );
51
+
52
+ expect(screen.queryByRole('row')).not.toBeInTheDocument();
53
+ });
54
+
55
+ test('Matches snapshot without children', () => {
56
+ const { asFragment } = render(
57
+ <table>
58
+ <tbody>
59
+ <Tr />
60
+ </tbody>
61
+ </table>
62
+ );
63
+
64
+ expect(asFragment()).toMatchSnapshot();
65
+ });
66
+
67
+ test('Matches snapshot with children', () => {
68
+ const { asFragment } = render(
69
+ <table>
70
+ <tbody>
71
+ <Tr>
72
+ <td>Row content</td>
73
+ </Tr>
74
+ </tbody>
75
+ </table>
76
+ );
77
+
78
+ expect(asFragment()).toMatchSnapshot();
79
+ });
@@ -0,0 +1,11 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`Matches snapshot 1`] = `
4
+ <DocumentFragment>
5
+ <div
6
+ class="pf-v6-c-table__expandable-row-content"
7
+ >
8
+ Row content
9
+ </div>
10
+ </DocumentFragment>
11
+ `;
@@ -0,0 +1,13 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`Matches snapshot without children 1`] = `
4
+ <DocumentFragment>
5
+ <table
6
+ class="pf-v6-c-table pf-m-grid-md"
7
+ data-ouia-component-id="OUIA-Generated-Table-9"
8
+ data-ouia-component-type="PF6/Table"
9
+ data-ouia-safe="true"
10
+ role="grid"
11
+ />
12
+ </DocumentFragment>
13
+ `;
@@ -0,0 +1,33 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`Matches snapshot with children 1`] = `
4
+ <DocumentFragment>
5
+ <table>
6
+ <tbody>
7
+ <tr>
8
+ <td
9
+ class="pf-v6-c-table__td"
10
+ tabindex="-1"
11
+ >
12
+ Cell content
13
+ </td>
14
+ </tr>
15
+ </tbody>
16
+ </table>
17
+ </DocumentFragment>
18
+ `;
19
+
20
+ exports[`Matches snapshot without children 1`] = `
21
+ <DocumentFragment>
22
+ <table>
23
+ <tbody>
24
+ <tr>
25
+ <td
26
+ class="pf-v6-c-table__td"
27
+ tabindex="-1"
28
+ />
29
+ </tr>
30
+ </tbody>
31
+ </table>
32
+ </DocumentFragment>
33
+ `;
@@ -0,0 +1,35 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`Matches snapshot with children 1`] = `
4
+ <DocumentFragment>
5
+ <table>
6
+ <tbody>
7
+ <tr
8
+ class="pf-v6-c-table__tr"
9
+ data-ouia-component-id="OUIA-Generated-TableRow-6"
10
+ data-ouia-component-type="PF6/TableRow"
11
+ data-ouia-safe="true"
12
+ >
13
+ <td>
14
+ Row content
15
+ </td>
16
+ </tr>
17
+ </tbody>
18
+ </table>
19
+ </DocumentFragment>
20
+ `;
21
+
22
+ exports[`Matches snapshot without children 1`] = `
23
+ <DocumentFragment>
24
+ <table>
25
+ <tbody>
26
+ <tr
27
+ class="pf-v6-c-table__tr"
28
+ data-ouia-component-id="OUIA-Generated-TableRow-5"
29
+ data-ouia-component-type="PF6/TableRow"
30
+ data-ouia-safe="true"
31
+ />
32
+ </tbody>
33
+ </table>
34
+ </DocumentFragment>
35
+ `;
@@ -184,6 +184,8 @@ To make a cell an action cell, render an `ActionsColumn` component inside a row'
184
184
 
185
185
  If actions menus are getting clipped by other items on the page, such as sticky columns or rows, the `ActionsColumn` can be passed a `menuAppendTo` prop to adjust where the actions menu is appended.
186
186
 
187
+ When a table row contains mixed content of text and interactive elements, the `hasAction` property may be passed to a `Td` which contains interactive content like the below example's start `Button`. This will align buttons and other elements with other cells' text. Note that `hasAction` should not be used with `Td`s in an `ActionsColumn` because that comes with it's own spacing.
188
+
187
189
  ```ts file="TableActions.tsx"
188
190
 
189
191
  ```
@@ -200,9 +202,10 @@ Using an `OverflowMenu` in the actions column, allowing the actions to condense
200
202
 
201
203
  To make a parent/child row pair expandable:
202
204
 
203
- 1. Make the first cell in every row an expandable cell by passing `TdExpandType` object to the `expand` prop on the `Td`
204
- 2. Wrap the content of each child row cell in `ExpandableRowContent`.
205
- 3. Enclose each parent/child row pair in a `Tbody` component with an `isExpanded` prop.
205
+ 1. Pass `isExpandable` to `Table`.
206
+ 1. Make the first cell in every row an expandable cell by passing `TdExpandType` object to the `expand` prop on the `Td`.
207
+ 1. Wrap the content of each child row cell in `ExpandableRowContent`.
208
+ 1. Pass `isExpanded` to `Tbody` and the `Tr` containing expandable content, and pass `isContentExpanded` to the `Tr` that acts as the "control row".
206
209
 
207
210
  The `TdExpandType` expects an `OnCollapse` event handler that has the following signature:
208
211
 
@@ -226,9 +229,10 @@ Note: Table column widths will respond automatically when toggling expanded rows
226
229
 
227
230
  To make a parent/child row pair compound expandable:
228
231
 
229
- 1. Pass a `TdCompoundExpandType` object to the `compoundExpand` prop on any `Td` that has an expandable child row
230
- 2. Wrap the content of each child row cell in `ExpandableRowContent`.
231
- 3. Each child `Tr` has an `isExpanded` prop.
232
+ 1. Pass `isExpandable` to `Table`.
233
+ 1. Pass a `TdCompoundExpandType` object to the `compoundExpand` prop on any `Td` that has an expandable child row.
234
+ 1. Wrap the content of each child row cell in `ExpandableRowContent`.
235
+ 1. Pass `isExpanded` to `Tbody` and the `Tr` containing expandable content, and pass `isContentExpanded` to the `Tr` that acts as the "control row".
232
236
 
233
237
  The `TdCompoundExpandType` expects an `OnExpand` event handler with the following signature
234
238
 
@@ -243,6 +247,8 @@ export type OnExpand = (
243
247
  ) => void;
244
248
  ```
245
249
 
250
+ For a more complex compound expandable implementation with nested tables, see our [table compound expansion demo](/components/table/react-demos/compound-expansion).
251
+
246
252
  ```ts file="TableCompoundExpandable.tsx"
247
253
 
248
254
  ```
@@ -146,7 +146,7 @@ export const TableActions: React.FunctionComponent = () => {
146
146
  <Td dataLabel={columnNames.prs}>{repo.prs}</Td>
147
147
  <Td dataLabel={columnNames.workspaces}>{repo.workspaces}</Td>
148
148
  <Td dataLabel={columnNames.lastCommit}>{repo.lastCommit}</Td>
149
- <Td dataLabel={columnNames.singleAction} modifier="fitContent">
149
+ <Td dataLabel={columnNames.singleAction} modifier="fitContent" hasAction>
150
150
  {singleActionButton}
151
151
  </Td>
152
152
  <Td isActionCell>