Skip to content

Refactoring EuiKeyPadMenuItem beta badge for improved accessibility#5508

Closed
1Copenut wants to merge 8 commits intoelastic:mainfrom
1Copenut:feature/tpierce-eui-5290
Closed

Refactoring EuiKeyPadMenuItem beta badge for improved accessibility#5508
1Copenut wants to merge 8 commits intoelastic:mainfrom
1Copenut:feature/tpierce-eui-5290

Conversation

@1Copenut
Copy link
Contributor

@1Copenut 1Copenut commented Dec 28, 2021

Summary

The EuiKeypadMenuItem had a focusable span inside the focusable button, used to trigger the tooltips. Axe-core was complaining about this nested focusable element, so I refactored it to move it outside the button as a sibling element. Closes #5290.

  • Moved the EuiBetaBadge outside the parent button
  • Updated the absolute positioning of the beta badge to match current
  • Added role="button" to beta badge span for more consistent SR read out
  • Added an aria-label to the beta badge span[role="button"] so it offers context to screen readers

Not sure this qualifies as a breaking change but it might. The refactoring of HTML was limited to EuiKeypadMenuItem in cases where the beta badge is present. Happy to flag it as a breaking change if reviewers feel it's warranted.

Checklist

* Moved the EuiBetaBadge outside the parent button
* Updated the absolute positioning of the beta badge to match current
* Added role="button" to beta badge span for more consistent SR read out
Copy link
Contributor Author

@1Copenut 1Copenut left a comment

Choose a reason for hiding this comment

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

Added comments about two of the proposed changes.

title={title || label}
>
<span tabIndex={0} className={classes} {...rest}>
<span tabIndex={0} className={classes} role="button" {...rest}>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added this role="button" because Safari + VoiceOver wasn't consistently announcing the tooltip. Found this article Short note on aria-label, aria-labelledby, and aria-describedby by Leonie Watson that gave me a clue the span alone might not honor our ARIA markup consistently.

}
}

.euiKeyPadMenuListItem {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved this out as a top-level element in the SCSS to ensure consistent absolute positioning and lessening risk of the cascade modifying something.

@1Copenut 1Copenut marked this pull request as ready for review December 28, 2021 20:48
@kibanamachine
Copy link

Preview documentation changes for this PR: https://eui.elastic.co/pr_5508/


return (
<EuiBetaBadge
aria-label={`${label}. Beta item.`}
Copy link
Contributor

Choose a reason for hiding this comment

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

Any hard coded text should use the useEuiI18n utility to allow localization.

Copy link
Contributor

Choose a reason for hiding this comment

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

@cchaos does this labelling match the intent of specifying an iconType?

Copy link
Contributor

Choose a reason for hiding this comment

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

My guess is that we should actually be labelling button as beta not the badge. And that we can’t hard-code “Beta item” at all, that the beta label needs to come from the betaBadgeLabel that the consumer supplies since it's not always going to mean "Beta" specifically.

@1Copenut I think we need to re-think this solution. Mainly, one of the issues I'm seeing is that if a consumer were to use EuiKeyPadMenuItem by itself, this beta badge would no longer be poisitioned against the button, but whatever next parent is position: relative.

Would it be a better solution to revert back the styling to include the beta badge within the button, but aria-hidden it and just apply the betaBadgeLabel as an extra aria-describedBy?

Copy link
Contributor Author

@1Copenut 1Copenut Jan 6, 2022

Choose a reason for hiding this comment

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

Thank you @cchaos for this use case my solution hadn't anticipated. I'll give it another pass in a new branch with the approach you outlined and keep things in sync here so we don't lose the history.

I talked about this with Chandler in our 1:1 yesterday. Refactored it to add a relatively positioned DIV. I couldn't keep the beta badge nested inside the button because the axe plugin was complaining about a nested element, and hiding it with aria-hidden="true" would have removed the tooltip context for screen readers.

Moving the beta badge out to a sibling of the button felt like the best approach to balance all concerns.

@1Copenut 1Copenut changed the title Refactoring EuiKeypadMenuItem beta badge for improved accessibility Refactoring EuiKeyPadMenuItem beta badge for improved accessibility Dec 29, 2021
@kibanamachine
Copy link

Preview documentation changes for this PR: https://eui.elastic.co/pr_5508/

},
className
);
const betaItemLabel = useEuiI18n('euiKeyPadMenuItem.betaLabel', 'Beta item.');
Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry, I could've provided more guidance on the i18n util; including the label variable here will make the whole label localizable, instead of forcing the order.

Suggested change
const betaItemLabel = useEuiI18n('euiKeyPadMenuItem.betaLabel', 'Beta item.');
const betaItemLabel = useEuiI18n(
'euiKeyPadMenuItem.betaLabel',
'{label}. Beta item.',
{ label }
);

and then,

aria-label={betaItemLabel}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll grab this on Tuesday morning right away!

@1Copenut 1Copenut requested a review from chandlerprall January 4, 2022 16:08
@kibanamachine
Copy link

Preview documentation changes for this PR: https://eui.elastic.co/pr_5508/

>
{renderContent()}
</Element>
<div className="euiKeyPadMenuItem__outer">
Copy link
Contributor Author

Choose a reason for hiding this comment

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

After talking with @chandlerprall on 1/10, I added a containing DIV to manage relative positioning inside the EuiKeypadMenuItem component. This addresses @cchaos concern that we might lose that reference if the component is used outside the original context, and maintains the fix to support mouse, keyboard, and screen reader (semantic) accessibility.

@kibanamachine
Copy link

Preview documentation changes for this PR: https://eui.elastic.co/pr_5508/

Copy link
Contributor

@cchaos cchaos left a comment

Choose a reason for hiding this comment

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

Thanks for looking into it @1Copenut.

I think we'll need to do more than just wrap with a relative div and shift some actual styles around. Specifically I'm looking at things that consumers may want to customize like sizing. Here's an example in Kibana that will break with this implementation:

https://github.com/elastic/kibana/blob/main/x-pack/plugins/cases/public/components/create/owner_selector.tsx#L46-L49


return (
<EuiBetaBadge
aria-label={betaItemLabel}
Copy link
Contributor

Choose a reason for hiding this comment

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

This beta label can't be hard-coded because it doesn't always actually mean "Beta".

Suggested change
aria-label={betaItemLabel}
aria-label={`${label} ${betaBadgeLabel}`}

>
{renderContent()}
</Element>
{betaBadgeLabel && !checkable && renderBetaBadge()}
Copy link
Contributor

@cchaos cchaos Jan 11, 2022

Choose a reason for hiding this comment

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

The betaBadgeLabel check is already in renderBetaBadge() so I'd just move the !checkable check into there as well, so you can simplify this to just:

Suggested change
{betaBadgeLabel && !checkable && renderBetaBadge()}
{renderBetaBadge()}

const renderContent = () => (
<span className="euiKeyPadMenuItem__inner">
{checkable ? renderCheckableElement() : renderBetaBadge()}
{checkable && renderCheckableElement()}
Copy link
Contributor

Choose a reason for hiding this comment

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

The checkable check is already in renderCheckableElement()

Suggested change
{checkable && renderCheckableElement()}
{renderCheckableElement()}

* Refactoring for variable container width.
* Adding two spans to ensure positioning and variable width to container.
@1Copenut 1Copenut requested a review from cchaos January 13, 2022 22:44
>
{renderContent()}
</Element>
<span className="euiKeyPadMenuItem__outer">
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought a lot about @cchaos comments the past couple of days. After a number of false starts, I settled on this solution. The euiKeyPadMenuItem__outer class allows consumers to extend the component width easily. The euiKeyPadMenuItem__positioned class sets a relative position reference and a max-width so buttons, links, and labels maintain the 96px width. Beta badges will also maintain their position next to the button as separate focusable elements.

@kibanamachine
Copy link

Preview documentation changes for this PR: https://eui.elastic.co/pr_5508/

@cchaos
Copy link
Contributor

cchaos commented Jan 14, 2022

@1Copenut I've opened a new PR to showcase an idea I had for this. I couldn't do a PR against this branch because there were too many undos to get to the original and I couldn't make one against your fork because your main branch was too out of date. So here it is: #5541

@1Copenut
Copy link
Contributor Author

Closing this PR for a more robust solution Caroline merged here #5541

@1Copenut 1Copenut closed this Jan 19, 2022
@1Copenut 1Copenut deleted the feature/tpierce-eui-5290 branch January 19, 2022 14:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[EuiKeyPadMenu][AXE-CORE]: Nested elements that can take focus will not be announced by screen readers

4 participants