-
Notifications
You must be signed in to change notification settings - Fork 844
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
[EuiCollapsibleNavBeta] Improve collapsed button icon screen reader UX #7055
Conversation
- instead of accepting any JSX/react node, *only* accept strings - This was checked with Tim Sullivan and confirmed to match Kibana usage
+ DRY out EuiToolTipAnchorProps types + fix Enzyme test causing false negatives in other tests
…bedby` - this prevents repeat/duplicate information, since `aria-label` and `aria-describedby` are the exact same content
- `id` is already destructured, no need to use `this.state`
- Remove className maps - they're not actually being used and we should be using more modern `as const`/`typeof` instead of `keysOf`
ebc851e
to
4ed760b
Compare
@@ -67,6 +67,7 @@ export const EuiCollapsedNavButton: FunctionComponent< | |||
return ( | |||
<EuiToolTip | |||
content={title} | |||
setAriaDescribedBy={false} // `title` content already set in `aria-label` below |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@1Copenut I could use your help testing this and verifying that it's actually doing anything. I originally thought it was necessary to unset aria-describedby
if aria-label
contained the same text, but now I'm not so sure.
-
In Safari+VO, VO appears to intelligently detect if they're the same and does not read out the
aria-describedby
text -
In FF+VO, VO reads out the label twice even if no
aria-describedby
is present, which I think is a bug with FF and should be ignored -
I have no idea what JAWS/NVDA do and I'd really appreciate your help figuring that out.
If it turns out that all screen readers successfully de-duplicate labels and descriptions that contain the same content, I'll likely go ahead and revert the part of this PR that adds the setAriaDescribedBy
prop entirely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cee-chen Can do. I'll get the JAWS license squared away and test it tomorrow morning if that works.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cee-chen I've started testing this afternoon. I won't be able to test JAWS and NVDA until we have a preview in Buildkite unless I get really lucky and get code compiled and running on the Windows machine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doh, I forgot about that, apologies. Can you use this proof-of-concept CodeSandbox in the interim?
https://codesandbox.io/s/strange-surf-xrxfd7?file=/demo.js
The first button has the same aria-label
and aria-describedby
, the second button has a separate label/description.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cee-chen Yes, that'll work great! I can test this immediately and provide feedback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this option to allow consumers to disable the aria-describedby
. Your comments inline are an excellent descriptor of when users might want to do that. Because we have the aria-label
for semantic labeling we shouldn't run afoul of automated checks, and the default experience is be to have aria-describedby
enabled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I don't think I made the original intent clear.
I was just asking you to test what happens when a button has both an aria-label
and an aria-describedby
with the same content. Do screen readers automatically de-duplicate that content, or do they read out both?
The second button was just there as a control for how screen readers behave without duplicated content. It's not an option for the beta collapsible nav.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, took a second run through and here's the results by pairing. I deleted my prior comment because it didn't apply to how I needed to be testing.
It's awesome that screen readers recognize duplicates for a fairly high number of pairings. NVDA on Chrome/Edge do repeat the content, but none of the three I tested on JAWS read back the description if it matched the label.
NVDA
- Chrome + NVDA repeats the description whether it's the same or different than the label:
- Title button, title
- Title button, description
- Edge + NVDA repeats the description whether it's the same or different than the label:
- Title button, title
- Title button, description
- Firefox + NVDA does not repeat the description if it matches the label:
- Title button
- Title button, description
JAWS
- Chrome + JAWS 23 does not repeat the description if it matches the label:
- Title button. To activate press Enter.
- Title button. To activate press Enter. Description.
- Edge + JAWS 23 does not repeat the description if it matches the label:
- Title button. To activate press Enter.
- Title button. To activate press Enter. Description.
- Firefox + JAWS 23 does not repeat the description if it matches the label:
- Title button. To activate press Enter.
- Title button. To activate press Enter. Description. Description.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's the results by pairing for second run, using the following test criteria. All tests were run using the same criteria. Start screen reader first, then start browser and navigate to the CodeSandbox page.
I want to test how a button without any
aria-describedby
compares to a button with the samearia-label/describedby
Button 1
has aria-label and aria-describedby.
Button 2
has aria-label only.
NVDA
- Chrome + NVDA
- Button 1: Title button. Title.
- Button 2: Title button.
- Edge + NVDA
- Button 1: Title button. Title.
- Button 2: Title button.
- Firefox + NVDA
- Button 1: Title button
- Button 2: Title button
JAWS
- Chrome + JAWS
- Button 1: Title button. To activate press Enter.
- Button 2: Title button. To activate press Enter.
- Edge + JAWS
- Button 1: Title button. To activate press Enter.
- Button 2: Title button. To activate press Enter.
- Firefox + JAWS
- Button 1: Title button. To activate press Enter.
- Button 2: Title button. To activate press Enter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Recap of our findings and discussions:
- All screen readers (i.e., JAWS & VO) except for NVDA on Chrome/Edge de-duplicate repeat content between
aria-label
andaria-describedby
- (worth noting: WebAim's latest screen reader survey lists a 16% user base of NVDA+Chrome)
- However, since this only affects 1 in 3 screen readers, we've decided to revert the new
setAriaDescribedBy
prop in this PR. The potential for degraded UX by allowing thearia-describedby
to be disabled is greater than the gain of not hearing a snippet of duplicated text.
Preview documentation changes for this PR: https://eui.elastic.co/pr_7055_buildkite/ |
Going to hold off on fixing the failing downstream snapshot tests until we know for sure if removing the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These changes look good @cee-chen. The screen readers tested well with your proof of concept code. I logged the pairings and speech read back for each. We won't completely eliminate duplicated text, but the experience is really solid.
I don't have any changes. Will mark this approved after a quick run-through on a build preview.
@@ -67,6 +67,7 @@ export const EuiCollapsedNavButton: FunctionComponent< | |||
return ( | |||
<EuiToolTip | |||
content={title} | |||
setAriaDescribedBy={false} // `title` content already set in `aria-label` below |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this option to allow consumers to disable the aria-describedby
. Your comments inline are an excellent descriptor of when users might want to do that. Because we have the aria-label
for semantic labeling we shouldn't run afoul of automated checks, and the default experience is be to have aria-describedby
enabled.
@@ -67,6 +67,7 @@ export const EuiCollapsedNavButton: FunctionComponent< | |||
return ( | |||
<EuiToolTip | |||
content={title} | |||
setAriaDescribedBy={false} // `title` content already set in `aria-label` below |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, took a second run through and here's the results by pairing. I deleted my prior comment because it didn't apply to how I needed to be testing.
It's awesome that screen readers recognize duplicates for a fairly high number of pairings. NVDA on Chrome/Edge do repeat the content, but none of the three I tested on JAWS read back the description if it matched the label.
NVDA
- Chrome + NVDA repeats the description whether it's the same or different than the label:
- Title button, title
- Title button, description
- Edge + NVDA repeats the description whether it's the same or different than the label:
- Title button, title
- Title button, description
- Firefox + NVDA does not repeat the description if it matches the label:
- Title button
- Title button, description
JAWS
- Chrome + JAWS 23 does not repeat the description if it matches the label:
- Title button. To activate press Enter.
- Title button. To activate press Enter. Description.
- Edge + JAWS 23 does not repeat the description if it matches the label:
- Title button. To activate press Enter.
- Title button. To activate press Enter. Description.
- Firefox + JAWS 23 does not repeat the description if it matches the label:
- Title button. To activate press Enter.
- Title button. To activate press Enter. Description. Description.
setAriaDescribedBy
prop
src/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_item.tsx
Outdated
Show resolved
Hide resolved
|
||
expect( | ||
getByTestSubject('anchor').getAttribute('aria-describedby') | ||
).toEqual('toolTipId customId'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this order of concatenation. Screen readers key off IDs in order, so it'll always read our described by text first, then additional.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 High five Cee. The VoiceOver tests are working great, announcing buttons as we expected. Axe is reporting 0 errors. This PR is good to 🚢
Preview documentation changes for this PR: https://eui.elastic.co/pr_7055_buildkite/ |
💚 Build Succeeded
History
|
`v86.0.0`⏩`v87.1.0`⚠️ The biggest set of type changes in this PR come from the breaking change that makes `pageSize` and `pageSizeOptions` now optional props for `EuiBasicTable.pagination`, `EuiInMemoryTable.pagination` and `EuiDataGrid.pagination`. This caused several other components that were cloning EUI's pagination type to start throwing type warnings about `pageSize` being optional. Where I came across these errors, I modified the extended types to require `pageSize`. These types and their usages may end up changing again in any case once the Shared UX team looks into #56406. --- ## [`87.1.0`](https://github.com/elastic/eui/tree/v87.1.0) - Updated the underlying library powering `EuiAutoSizer`. This primarily affects typing around the `disableHeight` and `disableWidth` props ([#6798](elastic/eui#6798)) - Added new `EuiAutoSize`, `EuiAutoSizeHorizontal`, and `EuiAutoSizeVertical` types to support `EuiAutoSizer`'s now-stricter typing ([#6798](elastic/eui#6798)) - Updated `EuiDatePickerRange` to support `compressed` display ([#7058](elastic/eui#7058)) - Updated `EuiFlyoutBody` with a new `scrollableTabIndex` prop ([#7061](elastic/eui#7061)) - Added a new `panelMinWidth` prop to `EuiInputPopover` ([#7071](elastic/eui#7071)) - Added a new `inputPopoverProps` prop for `EuiRange`s and `EuiDualRange`s with `showInput="inputWithPopover"` set ([#7082](elastic/eui#7082)) **Bug fixes** - Fixed `EuiToolTip` overriding instead of merging its `aria-describedby` tooltip ID with any existing `aria-describedby`s ([#7055](elastic/eui#7055)) - Fixed `EuiSuperDatePicker`'s `compressed` display ([#7058](elastic/eui#7058)) - Fixed `EuiAccordion` to remove tabbable children from sequential keyboard navigation when the accordion is closed ([#7064](elastic/eui#7064)) - Fixed `EuiFlyout`s to accept custom `aria-describedby` IDs ([#7065](elastic/eui#7065)) **Accessibility** - Removed the default `dialog` role and `tabIndex` from push `EuiFlyout`s. Push flyouts, compared to overlay flyouts, require manual accessibility management. ([#7065](elastic/eui#7065)) ## [`87.0.0`](https://github.com/elastic/eui/tree/v87.0.0) - Added beta `componentDefaults` prop to `EuiProvider`, which will allow configuring certain default props globally. This list of components and defaults is still under consideration. ([#6923](elastic/eui#6923)) - `EuiPortal`'s `insert` prop can now be configured globally via `EuiProvider.componentDefaults` ([#6941](elastic/eui#6941)) - `EuiFocusTrap`'s `crossFrame` and `gapMode` props can now be configured globally via `EuiProvider.componentDefaults` ([#6942](elastic/eui#6942)) - `EuiTablePagination`'s `itemsPerPage`, `itemsPerPageOptions`, and `showPerPageOptions` props can now be configured globally via `EuiProvider.componentDefaults` ([#6951](elastic/eui#6951)) - `EuiBasicTable`, `EuiInMemoryTable`, and `EuiDataGrid` now allow `pagination.pageSize` to be undefined. If undefined, `pageSize` defaults to `EuiTablePagination`'s `itemsPerPage` component default. ([#6993](elastic/eui#6993)) - `EuiBasicTable`, `EuiInMemoryTable`, and `EuiDataGrid`'s `pagination.pageSizeOptions` will now fall back to `EuiTablePagination`'s `itemsPerPageOptions` component default. ([#6993](elastic/eui#6993)) - Updated `EuiHeaderLinks`'s `gutterSize` spacings ([#7005](elastic/eui#7005)) - Updated `EuiHeaderAlert`'s stacking styles ([#7005](elastic/eui#7005)) - Added `toolTipProps` to `EuiListGroupItem` that allows customizing item tooltips. ([#7018](elastic/eui#7018)) - Updated `EuiBreadcrumbs` to support breadcrumbs that toggle popovers via `popoverContent` and `popoverProps` ([#7031](elastic/eui#7031)) - Improved the contrast ratio of disabled titles within `EuiSteps` and `EuiStepsHorizontal` to meet WCAG AA guidelines. ([#7032](elastic/eui#7032)) - Updated `EuiSteps` and `EuiStepsHorizontal` to highlight and provide a more clear visual indication of the current step ([#7048](elastic/eui#7048)) **Bug fixes** - Single uses of `<EuiHeaderSectionItem side="right" />` now align right as expected without needing a previous `side="left"` sibling. ([#7005](elastic/eui#7005)) - `EuiPageTemplate` now correctly displays `panelled={true}` ([#7044](elastic/eui#7044)) **Breaking changes** - `EuiTablePagination`'s default `itemsPerPage` is now `10` (was previously `50`). This can be configured through `EuiProvider.componentDefaults`. ([#6993](elastic/eui#6993)) - `EuiTablePagination`'s default `itemsPerPageOptions` is now `[10, 25, 50]` (was previously `[10, 20, 50, 100]`). This can be configured through `EuiProvider.componentDefaults`. ([#6993](elastic/eui#6993)) - Removed `border` prop from `EuiHeaderSectionItem` (unused since Amsterdam theme) ([#7005](elastic/eui#7005)) - Removed `borders` object configuration from `EuiHeader.sections` ([#7005](elastic/eui#7005)) **CSS-in-JS conversions** - Converted `EuiHeaderAlert` to Emotion; Removed unused `.euiHeaderAlert__dismiss` CSS ([#7005](elastic/eui#7005)) - Converted `EuiHeaderSection`, `EuiHeaderSectionItem`, and `EuiHeaderSectionItemButton` to Emotion ([#7005](elastic/eui#7005)) - Converted `EuiHeaderLinks` and `EuiHeaderLink` to Emotion; Removed `$euiHeaderLinksGutterSizes` Sass variables ([#7005](elastic/eui#7005)) - Removed `$euiHeaderBackgroundColor` Sass variable; use `$euiColorEmptyShade` instead ([#7005](elastic/eui#7005)) - Removed `$euiHeaderChildSize` Sass variable; use `$euiSizeXXL` instead ([#7005](elastic/eui#7005)) --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Patryk Kopyciński <contact@patrykkopycinski.com>
Summary
This PR:
Makes the typing of nav item
title
s stricter - they now must be strings and not ReactNodes (in order to supportaria-label
/title
type attributes)Sets an
aria-label
on all collapsed/docked button icon nav items (example below)which resolves the many warnings in tests as well as devtools:
However, adding anaria-label
to button icons with a tooltip wrapped around them leads to duplicated content, because thearia-label
andaria-describedby
contain the same exact content. The solution is to modifyEuiToolTip
to allow configuring disabling thearia-describedby
logic if necessary/if tooltip content is duplicative.QA
yarn storybook
initialIsCollapsed
properly, if you refresh the page and the button icons aren't present, simply click the collapse nav button in the top left corner)aria-describedby
:gh pr checkout TODO
(yarn storybook should update automatically)yarn storybook
aria-describedby
text:General checklist
and cypress tests