diff --git a/packages/react-core/src/demos/Filters/examples/FilterAttributeSearch.tsx b/packages/react-core/src/demos/Filters/examples/FilterAttributeSearch.tsx
index 71195ad840e..dfcb3c7ce59 100644
--- a/packages/react-core/src/demos/Filters/examples/FilterAttributeSearch.tsx
+++ b/packages/react-core/src/demos/Filters/examples/FilterAttributeSearch.tsx
@@ -651,7 +651,7 @@ export const FilterAttributeSearch: React.FunctionComponent = () => {
-
+
{columnNames.name}
{columnNames.threads}
{columnNames.apps}
diff --git a/packages/react-core/src/demos/Filters/examples/FilterCheckboxSelect.tsx b/packages/react-core/src/demos/Filters/examples/FilterCheckboxSelect.tsx
index 0fe3cb1c06a..dae722e2173 100644
--- a/packages/react-core/src/demos/Filters/examples/FilterCheckboxSelect.tsx
+++ b/packages/react-core/src/demos/Filters/examples/FilterCheckboxSelect.tsx
@@ -377,7 +377,7 @@ export const FilterCheckboxSelect: React.FunctionComponent = () => {
-
+
{columnNames.name}
{columnNames.threads}
{columnNames.apps}
diff --git a/packages/react-core/src/demos/Filters/examples/FilterFaceted.tsx b/packages/react-core/src/demos/Filters/examples/FilterFaceted.tsx
index d2315858746..9accf077041 100644
--- a/packages/react-core/src/demos/Filters/examples/FilterFaceted.tsx
+++ b/packages/react-core/src/demos/Filters/examples/FilterFaceted.tsx
@@ -467,7 +467,7 @@ export const FilterFaceted: React.FunctionComponent = () => {
-
+
{columnNames.name}
{columnNames.threads}
{columnNames.apps}
diff --git a/packages/react-core/src/demos/Filters/examples/FilterMixedSelectGroup.tsx b/packages/react-core/src/demos/Filters/examples/FilterMixedSelectGroup.tsx
index e5321c3277c..4991da5ad8b 100644
--- a/packages/react-core/src/demos/Filters/examples/FilterMixedSelectGroup.tsx
+++ b/packages/react-core/src/demos/Filters/examples/FilterMixedSelectGroup.tsx
@@ -517,7 +517,7 @@ export const FilterMixedSelectGroup: React.FunctionComponent = () => {
-
+
{columnNames.name}
{columnNames.threads}
{columnNames.apps}
diff --git a/packages/react-core/src/demos/Filters/examples/FilterSameSelectGroup.tsx b/packages/react-core/src/demos/Filters/examples/FilterSameSelectGroup.tsx
index e8c74d36c98..975dfdc5dc9 100644
--- a/packages/react-core/src/demos/Filters/examples/FilterSameSelectGroup.tsx
+++ b/packages/react-core/src/demos/Filters/examples/FilterSameSelectGroup.tsx
@@ -490,7 +490,7 @@ export const FilterSameSelectGroup: React.FunctionComponent = () => {
-
+
{columnNames.name}
{columnNames.threads}
{columnNames.apps}
diff --git a/packages/react-core/src/demos/Filters/examples/FilterSearchInput.tsx b/packages/react-core/src/demos/Filters/examples/FilterSearchInput.tsx
index 46111ca27bb..39e352dee9c 100644
--- a/packages/react-core/src/demos/Filters/examples/FilterSearchInput.tsx
+++ b/packages/react-core/src/demos/Filters/examples/FilterSearchInput.tsx
@@ -298,7 +298,7 @@ export const FilterSearchInput: React.FunctionComponent = () => {
-
+
{columnNames.name}
{columnNames.threads}
{columnNames.apps}
diff --git a/packages/react-core/src/demos/Filters/examples/FilterSingleSelect.tsx b/packages/react-core/src/demos/Filters/examples/FilterSingleSelect.tsx
index e1ebd4cd9da..f17ec50f154 100644
--- a/packages/react-core/src/demos/Filters/examples/FilterSingleSelect.tsx
+++ b/packages/react-core/src/demos/Filters/examples/FilterSingleSelect.tsx
@@ -362,7 +362,7 @@ export const FilterSingleSelect: React.FunctionComponent = () => {
-
+
{columnNames.name}
{columnNames.threads}
{columnNames.apps}
diff --git a/packages/react-core/src/demos/examples/Card/CardStatus.tsx b/packages/react-core/src/demos/examples/Card/CardStatus.tsx
index d74d250af67..05a6ffa0cf2 100644
--- a/packages/react-core/src/demos/examples/Card/CardStatus.tsx
+++ b/packages/react-core/src/demos/examples/Card/CardStatus.tsx
@@ -94,7 +94,7 @@ export const CardStatus: React.FunctionComponent = () => {
-
+
{columns.map((column, columnIndex) => (
{column}
diff --git a/packages/react-core/src/demos/examples/Tabs/TabsAndTable.tsx b/packages/react-core/src/demos/examples/Tabs/TabsAndTable.tsx
index be81a405e79..af9f9a43bd0 100644
--- a/packages/react-core/src/demos/examples/Tabs/TabsAndTable.tsx
+++ b/packages/react-core/src/demos/examples/Tabs/TabsAndTable.tsx
@@ -230,7 +230,7 @@ export const TablesAndTabs = () => {
-
+
{columnNames.name}
{columnNames.branches}
{columnNames.prs}
diff --git a/packages/react-integration/cypress/integration/tableselectable.spec.ts b/packages/react-integration/cypress/integration/tableselectable.spec.ts
index 4d32223c653..7b058348994 100644
--- a/packages/react-integration/cypress/integration/tableselectable.spec.ts
+++ b/packages/react-integration/cypress/integration/tableselectable.spec.ts
@@ -12,10 +12,7 @@ describe('Table Selectable Test', () => {
});
it('Check number of columns', () => {
- cy.get('thead').find('th').should('have.length', 5);
-
- // There should be a canSelectAll input
- cy.get('thead').find('td').should('have.length', 1);
+ cy.get('thead').find('th').should('have.length', 6);
});
it('Test selectable checkbox', () => {
diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TableDemo/TableComposableDemo.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TableDemo/TableComposableDemo.tsx
index 833ee8fa284..8c1e334283f 100644
--- a/packages/react-integration/demo-app-ts/src/components/demos/TableDemo/TableComposableDemo.tsx
+++ b/packages/react-integration/demo-app-ts/src/components/demos/TableDemo/TableComposableDemo.tsx
@@ -347,7 +347,7 @@ export const TableComposableDemo = () => {
-
+
{columns[0]}
{columns[1]}
{columns[2]}
@@ -439,7 +439,7 @@ export const TableComposableDemo = () => {
{columns[2]}
{columns[3]}
{columns[4]}
-
+
@@ -616,7 +616,7 @@ export const TableComposableDemo = () => {
-
+
{columns[0]}
{columns[1]}
{columns[2]}
diff --git a/packages/react-table/src/components/Table/Th.tsx b/packages/react-table/src/components/Table/Th.tsx
index aaa07a5bcfe..5729f59c840 100644
--- a/packages/react-table/src/components/Table/Th.tsx
+++ b/packages/react-table/src/components/Table/Th.tsx
@@ -56,6 +56,14 @@ export interface ThProps
stickyRightOffset?: string;
/** Indicates the is part of a subheader of a nested header */
isSubheader?: boolean;
+ /** Visually hidden text accessible only via assistive technologies. This must be passed in if the
+ * th is intended to be visually empty, and must be conveyed as a column header text.
+ */
+ screenReaderText?: string;
+ /** Provides an accessible name to the th. This should only be passed in when the th contains only non-text
+ * content, such as a "select all" checkbox or "expand all" toggle.
+ */
+ 'aria-label'?: string;
}
const ThBase: React.FunctionComponent = ({
@@ -83,8 +91,17 @@ const ThBase: React.FunctionComponent = ({
stickyLeftOffset,
stickyRightOffset,
isSubheader = false,
+ screenReaderText,
+ 'aria-label': ariaLabel,
...props
}: ThProps) => {
+ if (!children && !screenReaderText && !ariaLabel) {
+ // eslint-disable-next-line no-console
+ console.warn(
+ 'Th: Table headers must have an accessible name. If the Th is intended to be visually empty, pass in screenReaderText. If the Th contains only non-text, interactive content such as a checkbox or expand toggle, pass in an aria-label.'
+ );
+ }
+
const [showTooltip, setShowTooltip] = React.useState(false);
const [truncated, setTruncated] = React.useState(false);
const cellRef = innerRef ? innerRef : React.createRef();
@@ -188,8 +205,9 @@ const ThBase: React.FunctionComponent = ({
onBlur={() => setShowTooltip(false)}
data-label={dataLabel}
onMouseEnter={tooltip !== null ? onMouseEnter : onMouseEnterProp}
- scope={component === 'th' && children ? scope : null}
+ scope={component === 'th' ? scope : null}
ref={cellRef}
+ aria-label={ariaLabel}
className={css(
styles.tableTh,
className,
@@ -212,7 +230,7 @@ const ThBase: React.FunctionComponent = ({
} as React.CSSProperties
})}
>
- {transformedChildren}
+ {transformedChildren || (screenReaderText && {screenReaderText} )}
);
diff --git a/packages/react-table/src/components/Table/__tests__/Th.test.tsx b/packages/react-table/src/components/Table/__tests__/Th.test.tsx
new file mode 100644
index 00000000000..ab4f71cf7bc
--- /dev/null
+++ b/packages/react-table/src/components/Table/__tests__/Th.test.tsx
@@ -0,0 +1,31 @@
+import * as React from 'react';
+import { render, screen } from '@testing-library/react';
+import { Th } from '../Th';
+
+test('Does not render with aria-label by default', () => {
+ render( );
+ expect(screen.getByRole('columnheader')).not.toHaveAccessibleName();
+});
+
+test('Renders with aria-label when passed in', () => {
+ render( );
+ expect(screen.getByRole('columnheader')).toHaveAccessibleName('Test');
+});
+
+test('Does not render with screen reader text by default', () => {
+ render( );
+
+ expect(screen.getByRole('columnheader')).toBeEmptyDOMElement();
+});
+
+test('Does not render with screen reader text when children are passed in', () => {
+ render(Heading label );
+
+ expect(screen.getByRole('columnheader')).not.toHaveTextContent('Test');
+});
+
+test('Renders with screen reader text when screenReaderText is passed in', () => {
+ render( );
+
+ expect(screen.getByRole('columnheader')).toHaveTextContent('Test');
+});
diff --git a/packages/react-table/src/components/Table/examples/TableActions.tsx b/packages/react-table/src/components/Table/examples/TableActions.tsx
index 9d42be87717..64ab513762f 100644
--- a/packages/react-table/src/components/Table/examples/TableActions.tsx
+++ b/packages/react-table/src/components/Table/examples/TableActions.tsx
@@ -116,8 +116,8 @@ export const TableActions: React.FunctionComponent = () => {
{columnNames.prs}
{columnNames.workspaces}
{columnNames.lastCommit}
-
-
+
+
diff --git a/packages/react-table/src/components/Table/examples/TableActionsOverflow.tsx b/packages/react-table/src/components/Table/examples/TableActionsOverflow.tsx
index 5ae2296e33e..e997f7b00d7 100644
--- a/packages/react-table/src/components/Table/examples/TableActionsOverflow.tsx
+++ b/packages/react-table/src/components/Table/examples/TableActionsOverflow.tsx
@@ -66,7 +66,7 @@ export const TableActions: React.FunctionComponent = () => {
{columnNames.prs}
{columnNames.workspaces}
{columnNames.lastCommit}
-
+
diff --git a/packages/react-table/src/components/Table/examples/TableCompoundExpandable.tsx b/packages/react-table/src/components/Table/examples/TableCompoundExpandable.tsx
index 4f90875d3c5..6e4253e88b7 100644
--- a/packages/react-table/src/components/Table/examples/TableCompoundExpandable.tsx
+++ b/packages/react-table/src/components/Table/examples/TableCompoundExpandable.tsx
@@ -67,7 +67,7 @@ export const TableCompoundExpandable: React.FunctionComponent = () => {
{columnNames.prs}
{columnNames.workspaces}
{columnNames.lastCommit}
-
+
{repositories.map((repo: Repository, rowIndex: number) => {
diff --git a/packages/react-table/src/components/Table/examples/TableDraggable.tsx b/packages/react-table/src/components/Table/examples/TableDraggable.tsx
index d37a0307617..7abcf7b7640 100644
--- a/packages/react-table/src/components/Table/examples/TableDraggable.tsx
+++ b/packages/react-table/src/components/Table/examples/TableDraggable.tsx
@@ -140,10 +140,10 @@ export const TableDraggable: React.FunctionComponent = () => {
];
return (
-
+
-
+
{columns.map((column, columnIndex) => (
{column}
))}
diff --git a/packages/react-table/src/components/Table/examples/TableExpandable.tsx b/packages/react-table/src/components/Table/examples/TableExpandable.tsx
index 7cb8ab08e11..67d1291348a 100644
--- a/packages/react-table/src/components/Table/examples/TableExpandable.tsx
+++ b/packages/react-table/src/components/Table/examples/TableExpandable.tsx
@@ -120,7 +120,7 @@ export const TableExpandable: React.FunctionComponent = () => {
-
+
{columnNames.name}
{columnNames.branches}
{columnNames.prs}
diff --git a/packages/react-table/src/components/Table/examples/TableNestedExpandable.tsx b/packages/react-table/src/components/Table/examples/TableNestedExpandable.tsx
index cee6e77f2a1..f2ef7359dcc 100644
--- a/packages/react-table/src/components/Table/examples/TableNestedExpandable.tsx
+++ b/packages/react-table/src/components/Table/examples/TableNestedExpandable.tsx
@@ -64,7 +64,7 @@ export const TableNestedExpandable: React.FunctionComponent = () => {
-
+
{columnNames.team}
diff --git a/packages/react-table/src/components/Table/examples/TableNestedStickyHeader.tsx b/packages/react-table/src/components/Table/examples/TableNestedStickyHeader.tsx
index 51edc7ec832..fe7b2d90704 100644
--- a/packages/react-table/src/components/Table/examples/TableNestedStickyHeader.tsx
+++ b/packages/react-table/src/components/Table/examples/TableNestedStickyHeader.tsx
@@ -154,6 +154,9 @@ export const TableNestedHeaders: React.FunctionComponent = () => {
{columnNames.destination}
+ {/* TODO: Remove the following Tr once Core updates towards https://github.com/patternfly/patternfly/issues/6272
+ are made for the v5 branch. For v6 branch the row can be removed immediately.
+ */}
diff --git a/packages/react-table/src/components/Table/examples/TableNestedTableExpandable.tsx b/packages/react-table/src/components/Table/examples/TableNestedTableExpandable.tsx
index 59855116a9c..37570aa540d 100644
--- a/packages/react-table/src/components/Table/examples/TableNestedTableExpandable.tsx
+++ b/packages/react-table/src/components/Table/examples/TableNestedTableExpandable.tsx
@@ -131,7 +131,7 @@ export const TableExpandable: React.FunctionComponent = () => {
-
+
{columnNames.name}
{columnNames.branches}
{columnNames.prs}
diff --git a/packages/react-table/src/components/Table/examples/TableSelectableRadio.tsx b/packages/react-table/src/components/Table/examples/TableSelectableRadio.tsx
index 710c19655cd..e932fdf30ba 100644
--- a/packages/react-table/src/components/Table/examples/TableSelectableRadio.tsx
+++ b/packages/react-table/src/components/Table/examples/TableSelectableRadio.tsx
@@ -35,7 +35,7 @@ export const TableSelectableRadio: React.FunctionComponent = () => {
-
+
{columnNames.name}
{columnNames.branches}
{columnNames.prs}
diff --git a/packages/react-table/src/components/Table/examples/TableStripedExpandable.tsx b/packages/react-table/src/components/Table/examples/TableStripedExpandable.tsx
index ddfd7dee692..e46c7bb61ef 100644
--- a/packages/react-table/src/components/Table/examples/TableStripedExpandable.tsx
+++ b/packages/react-table/src/components/Table/examples/TableStripedExpandable.tsx
@@ -115,7 +115,7 @@ export const TableStripedExpandable: React.FunctionComponent = () => {
-
+
{columnNames.name}
{columnNames.branches}
{columnNames.prs}
diff --git a/packages/react-table/src/components/Table/utils/decorators/selectable.tsx b/packages/react-table/src/components/Table/utils/decorators/selectable.tsx
index b49c947aeeb..71362242176 100644
--- a/packages/react-table/src/components/Table/utils/decorators/selectable.tsx
+++ b/packages/react-table/src/components/Table/utils/decorators/selectable.tsx
@@ -61,7 +61,7 @@ export const selectable: ITransform = (
return {
className: css(styles.tableCheck),
- component: 'td',
+ component: rowId !== -1 ? 'td' : 'th',
isVisible: !rowData || !rowData.fullWidth,
children: (
{
-
+
{columns[0]}
{columns[1]}
{columns[2]}
diff --git a/packages/react-table/src/demos/examples/TableCompoundExpansion.tsx b/packages/react-table/src/demos/examples/TableCompoundExpansion.tsx
index 3d3ee1e7977..3a04d2c5bbb 100644
--- a/packages/react-table/src/demos/examples/TableCompoundExpansion.tsx
+++ b/packages/react-table/src/demos/examples/TableCompoundExpansion.tsx
@@ -51,7 +51,7 @@ export const TableCompoundExpansion: React.FunctionComponent = () => {
{columnNames.description}
{columnNames.date}
{columnNames.status}
-
+
@@ -205,7 +205,8 @@ export const TableCompoundExpansion: React.FunctionComponent = () => {
{columnNames.prs}
{columnNames.workspaces}
{columnNames.lastCommit}
-
+
+
{repositories.map((repo, rowIndex) => {
diff --git a/packages/react-table/src/deprecated/components/Table/__tests__/__snapshots__/Table.test.tsx.snap b/packages/react-table/src/deprecated/components/Table/__tests__/__snapshots__/Table.test.tsx.snap
index 622d6ed898f..91e79a7ef26 100644
--- a/packages/react-table/src/deprecated/components/Table/__tests__/__snapshots__/Table.test.tsx.snap
+++ b/packages/react-table/src/deprecated/components/Table/__tests__/__snapshots__/Table.test.tsx.snap
@@ -1366,6 +1366,7 @@ exports[`Table Collapsible nested table 1`] = `
class="pf-v5-c-table__th"
data-key="0"
data-label=""
+ scope=""
tabindex="-1"
/>
-
@@ -4146,7 +4149,7 @@ exports[`Table Selectable table 1`] = `
type="checkbox"
/>
-
+
-
@@ -5539,7 +5544,7 @@ exports[`Table Selectable table with selected expandable row 1`] = `
type="checkbox"
/>
-
+