Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[A11y] [Table] Improvements to Screen Reader Functionality for Sortable Table Header Buttons #8092

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,11 @@ exports[`EuiBasicTable renders (kitchen sink) with pagination, selection, sortin
>
your name
</span>
<span
class="emotion-euiScreenReaderOnly"
>
Sorted ascending. Click to sort descending
</span>
<span
class="euiTableSortIcon"
data-euiicon-type="sortUp"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,8 @@ describe('EuiBasicTable', () => {
expect(
container.querySelector('[aria-sort="ascending"] .euiTableCellContent')
?.textContent
).toEqual('Name');
// Using toMatch because the text includes screen reader only text.
).toMatch('Name');
});

test('with sortable columns and sorting disabled', () => {
Expand Down
1 change: 1 addition & 0 deletions packages/eui/src/components/basic_table/basic_table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,7 @@ export class EuiBasicTable<T extends object = any> extends Component<
: undefined;
sorting.onSort = this.resolveColumnOnSort(column);
sorting.readOnly = this.props.sorting.readOnly || readOnly;
sorting.allowNeutralSort = this.props.sorting.allowNeutralSort;
}
headers.push(
<EuiTableHeaderCell
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ exports[`EuiTableHeaderCell sorting renders a button with onSort 1`] = `
>
Test
</span>
<span
class="emotion-euiScreenReaderOnly"
>
Sorted descending. Click to unsort
</span>
<span
class="euiTableSortIcon"
data-euiicon-type="sortDown"
Expand Down Expand Up @@ -234,6 +239,11 @@ exports[`EuiTableHeaderCell sorting renders with a sortable icon if \`onSort\` i
>
Test
</span>
<span
class="emotion-euiScreenReaderOnly"
>
Unsorted. Click to sort ascending
</span>
<span
class="euiTableSortIcon euiTableSortIcon--sortable"
color="subdued"
Expand Down
70 changes: 69 additions & 1 deletion packages/eui/src/components/table/table_header_cell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import React, {
HTMLAttributes,
ThHTMLAttributes,
ReactNode,
useMemo,
} from 'react';
import classNames from 'classnames';

Expand All @@ -19,7 +20,7 @@ import {
HorizontalAlignment,
LEFT_ALIGNMENT,
} from '../../services';
import { EuiI18n } from '../i18n';
import { EuiI18n, useEuiI18n } from '../i18n';
import { EuiScreenReaderOnly } from '../accessibility';
import { CommonProps, NoArgCallback } from '../common';
import { EuiIcon } from '../icon';
Expand Down Expand Up @@ -54,8 +55,62 @@ export type EuiTableHeaderCellProps = CommonProps &
* Used by EuiBasicTable to render hidden copy markers
*/
append?: ReactNode;
allowNeutralSort?: boolean;
};

const SortScreenReaderText = ({
isSorted,
isSortAscending,
allowNeutralSort,
}: {
isSorted: boolean | undefined;
isSortAscending: boolean | undefined;
allowNeutralSort: boolean | undefined;
}) => {
const unsortedText = useEuiI18n(
'euiTableHeaderCell.unsorted',
'Unsorted. Click to sort ascending'
);
const sortedAscendingText = useEuiI18n(
'euiTableHeaderCell.sortedAscending',
'Sorted ascending. Click to sort descending'
);
const sortedDescendingText = useEuiI18n(
'euiTableHeaderCell.sortedDescending',
'Sorted descending. Click to sort ascending'
);
const sortedDescendingUnsortText = useEuiI18n(
'euiTableHeaderCell.sortedDescendingUnsort',
'Sorted descending. Click to unsort'
);
const text = useMemo(() => {
if (!isSorted) {
return unsortedText;
}
if (isSortAscending) {
return sortedAscendingText;
}
if (allowNeutralSort === false) {
return sortedDescendingText;
}
return sortedDescendingUnsortText;
}, [
isSorted,
isSortAscending,
allowNeutralSort,
unsortedText,
sortedAscendingText,
sortedDescendingText,
sortedDescendingUnsortText,
]);

return (
<EuiScreenReaderOnly>
<span>{text}</span>
</EuiScreenReaderOnly>
);
};

const CellContents = ({
className,
align,
Expand All @@ -64,6 +119,7 @@ const CellContents = ({
canSort,
isSorted,
isSortAscending,
sortScreenReaderText,
}: {
className?: string;
align: HorizontalAlignment;
Expand All @@ -72,6 +128,7 @@ const CellContents = ({
canSort?: boolean;
isSorted: EuiTableHeaderCellProps['isSorted'];
isSortAscending?: EuiTableHeaderCellProps['isSortAscending'];
sortScreenReaderText?: ReactNode;
}) => {
return (
<EuiTableCellContent
Expand Down Expand Up @@ -104,6 +161,7 @@ const CellContents = ({
<span>{description}</span>
</EuiScreenReaderOnly>
)}
{sortScreenReaderText}
{isSorted ? (
<EuiIcon
className="euiTableSortIcon"
Expand Down Expand Up @@ -136,6 +194,7 @@ export const EuiTableHeaderCell: FunctionComponent<EuiTableHeaderCellProps> = ({
readOnly,
description,
append,
allowNeutralSort,
...rest
}) => {
const styles = useEuiMemoizedStyles(euiTableHeaderFooterCellStyles);
Expand All @@ -159,6 +218,14 @@ export const EuiTableHeaderCell: FunctionComponent<EuiTableHeaderCellProps> = ({
ariaSortValue = 'none';
}

const sortScreenReaderText = canSort ? (
<SortScreenReaderText
isSorted={isSorted}
isSortAscending={isSortAscending}
allowNeutralSort={allowNeutralSort}
/>
) : undefined;

const cellContentsProps = {
css: styles.euiTableHeaderCell__content,
align,
Expand All @@ -167,6 +234,7 @@ export const EuiTableHeaderCell: FunctionComponent<EuiTableHeaderCellProps> = ({
isSorted,
isSortAscending,
children,
sortScreenReaderText,
};

return (
Expand Down
Loading