Skip to content
This repository has been archived by the owner on May 24, 2024. It is now read-only.

Enhance screen reader support to announce column headers are interactable. #1836

Merged
merged 74 commits into from
Oct 25, 2023

Conversation

KoushikKalli
Copy link
Contributor

Summary

Added additional screen reader support to announce that column headers are interactable upon selection by giving focus to the button control that allows column headers to be selected.

What was changed:
Focus of a column header cell is changed from the cell to the button control inside the cell that allows selection.

Why it was changed:
To ensure screen readers announce that column headers are interactable upon selection.

Testing

This change was tested using:

  • WDIO
  • Jest
  • Visual testing (please attach a screenshot or recording)
  • Other (please describe below)
  • No tests are needed

Reviews

In addition to engineering reviews, this PR needs:

  • UX review
  • Accessibility review
  • Functional review

This PR resolves: UXPLATFORM-9611

@sdadn sdadn force-pushed the wdg_column_resizing branch from 0178357 to a4d7f99 Compare October 23, 2023 17:07
@chrismichalewicz
Copy link

@KoushikKalli @brithom Tested for accessibility. Looks good, great job! Updating the label to a11y reviewed.
Tested with Edge and JAWS 2022.2202.38
The screen reader communicated appropriately on a sortable column header 'to activate press enter', upon pressing enter the sort updated appropriately

Comment on lines +595 to +599
const onBlur = (event) => {
if (!event.currentTarget.contains(event.relatedTarget)) {
setGridHasFocus(false);
}
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not need to add new event handler logic to determine if the grid has focus.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the grid loses focus, we want the columnHeaderCell that had focus to reflect the correct state.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But the column header cell would lose focus itself. We should not need a state update because the CSS is based on focus, right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The columnHeaderCell's active state is set via a prop so if we do not do this here, the columnHeaderCell would have lost focus but its active state would remain true. The result is that when focus comes back into the grid, the columnHeaderCell will not get re-rendered thus causing incorrect screen reader behavior because focus is not correctly set to the button.

@@ -584,12 +585,19 @@ const DataGrid = injectIntl((props) => {
// Not triggered when swapping focus between children
if (handleFocus.current) {
setFocusedRowCol(focusedRow, focusedCol, true);
setGridHasFocus(true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would think that we could determine this information without needing to alter the focus event handler logic.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is where this logic should live. When the grid is initially rendered, nothing on the grid has focus. All the columnHeaderCells would be rendered with isActive=false. When the grid gets focus, since nothing is getting re-rendered, the state of the columnHeaderCell that got focus is incorrect. This ensures that when the grid gets focus the columnHeaderCell with the focus gets updated correctly.


const [isResizeHandleActive, setResizeHandleActive] = useState(false);

const columnHeaderFocusArea = useCallback(() => (columnHeaderCellButtonRef.current ? columnHeaderCellButtonRef.current : columnHeaderCellRef.current), []);
Copy link
Contributor

@cm9361 cm9361 Oct 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need a useCallback here? This should really just be a simple or statement to obtain this value, when needed. I could maybe see it being a ref variable. It just needs to be set at the proper time.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on where it is called from, the useCallback is required. We did not want to do the same or statement in multiple places.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can't we just use a ref variable?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So is your concern about the use of a function vs a variable. There is no reason we could not have used a ref but we used a function. Does it really matter (asking for a friend ;-))?

<div className={cx('header-container')} role={displayName && 'button'}>
<div
className={cx('header-container')}
{...isSelectable && displayName && { ref: columnHeaderCellButtonRef, tabIndex: '-1', role: 'button' }}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't work properly for the Terra Table. In that scenario, the tabIndex would be 0. Also, should the cell tabIndex be updated when this one is set? Would the cell ever have focus in that use case?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that if refactoring is needed for table then it should be done at that level. We have added the requisite tests to ensure that the grid functionality is preserved if such refactoring becomes necessary. The cell has a tabIndex of -1 and I do not think that needs to change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might be able to get away with it since the button is taking up most of the area. Ideally, the cell itself would not get focus when there is a button.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are correct. The cell will not get focus when there is a button.

@github-actions github-actions bot temporarily deployed to preview-pr-1836 October 24, 2023 20:00 Destroyed
Base automatically changed from wdg_column_resizing to wdg_column_resizing_feature October 25, 2023 13:17
@sdadn sdadn merged commit fe7af39 into wdg_column_resizing_feature Oct 25, 2023
@sdadn sdadn changed the title UXPLATFORM-9611: Enhance screen reader support to announce column headers are interactable. Enhance screen reader support to announce column headers are interactable. Oct 25, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants