-
Notifications
You must be signed in to change notification settings - Fork 205
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
build: leverage eslint--plugin-lit-a11y #976
Conversation
103d840
to
209b03d
Compare
"sp-radio", | ||
"sp-switch", | ||
"sp-menu-item", | ||
"sp-clear-button", |
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.
We know that all of the above element have interactive descendent that would associate key
events with any click
events for which we are listening, so allow.
"sp-switch", | ||
"sp-menu-item", | ||
"sp-clear-button", | ||
"sp-underlay" |
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.
This element doesn't explicitly have an interactive descendent, but the underlay of modal content (event when it "dismisses" the modal content) isn't focusable, so it would never receive key
events anyways.
const next = target.nextElementSibling as Dropdown; | ||
if (!next || next.open) return; | ||
next.click(); | ||
} | ||
|
||
private onKeypressLabel(event: KeyboardEvent & { target: HTMLElement }) { |
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.
The label isn't technically focusable, so this code path will likely never be met, but, inline with the comment in line 108, this is manual code while #475 is yet to be addressed.
<aside> | ||
<div id="nav-header"> | ||
<div id="logo-container"> | ||
<a href="#"> | ||
<a href="#index"> |
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.
We've gone back and forth on whether this rule is required. #
is technically a legit destination, but not explicit. Any insight on the accessibility of #
vs #index
or #top
will be submitted back to the linter!
"sp-menu-item", | ||
"sp-clear-button", | ||
"sp-underlay", | ||
"sp-popover" |
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 know in this file this element has interactive children, but not in others. We have the ability to skip this rule in ALL custom elements, but seems like an over step...
@@ -23,7 +23,7 @@ export default { | |||
export const Default = (): TemplateResult => { | |||
return html` | |||
<sp-asset style="height: 128px"> | |||
<img src=${portrait} alt="Demo Image" /> | |||
<img src=${portrait} alt="Demo Graphic" /> |
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.
Everywhere I switch Image
to Graphic
is in a demo or test, but it seems like good practice to get into.
@@ -196,7 +196,6 @@ export const withIcon = (): TemplateResult => { | |||
viewBox="0 0 36 36" | |||
focusable="false" | |||
aria-hidden="true" | |||
role="img" |
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.
role="img"
isn't really needed with aria-hidden="true"
...
@@ -46,7 +46,7 @@ export class MenuGroup extends SpectrumElement { | |||
<span class="header" id=${labelledby} aria-hidden="true"> | |||
<slot name="header"></slot> | |||
</span> | |||
<div aria-labelledby=${labelledby} role="none"> | |||
<div aria-labelledby=${labelledby} role="presentation"> |
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.
IIUC, presentation
allows the pass through without expecting this <div>
to have actual role content.
@@ -72,6 +72,7 @@ export class OverlayTrigger extends LitElement { | |||
<div | |||
id="trigger" | |||
@click=${this.onTrigger} | |||
@keypress=${this.onKeypress} |
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.
We can't guarantee that a user uses an interactive element below here, so I've added keypress
with some gating, just in case. Could be over kill...
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.
This does feel like overkill to me. I'd rather just see the documentation cover this.
In general I think we should document and have examples of best practices, and not try to "fix" bad practices.
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.
This makes sense to me. I'll work on the right way to skip this rule here and add a sentence or two to the documentation for this.
209b03d
to
b728e7f
Compare
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.
One change request and one question. Overall looks good!
display: none; | ||
pointer-events: none; | ||
opacity: 0; | ||
} |
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.
How do these css changes relate to the linting change?
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.
Indeed. I should be able to take even more of this away as we're moving from a <div>
element here that would require special rule skipping or keyboard event handling in exchange for an <sp-underlay>
element that already has agreement with the lint rules. Will fix!
@@ -72,6 +72,7 @@ export class OverlayTrigger extends LitElement { | |||
<div | |||
id="trigger" | |||
@click=${this.onTrigger} | |||
@keypress=${this.onKeypress} |
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.
This does feel like overkill to me. I'd rather just see the documentation cover this.
In general I think we should document and have examples of best practices, and not try to "fix" bad practices.
b728e7f
to
39283c3
Compare
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.
Updates look great. Nice!
|
||
## Accessibility | ||
|
||
When using an `<overlay-trigger>` element, it is important to be sure the that content you project into `slot="trigger"` is "interactive". This means that an element within that branch of DOM will be able to receive focus and said element will appropriately convert keyboard interactions to `click` events similar to what you find with `<a href="#">Anchors</a>`, `<button>Buttons</button>`, etc. You can find further reading on the subject of accessible keyboard interactions at [https://www.w3.org/WAI/WCAG21/Understanding/keyboard](https://www.w3.org/WAI/WCAG21/Understanding/keyboard). |
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.
Nice!
39283c3
to
257a0fc
Compare
Description
Use
eslint-plugin-lit-a11y
. Make changes to support its findings. I'll comment a bunch inline so we can discuss whether there are additional settings/considerations we'd like to take into account.Motivation and Context
The level of accessibility that our elements deliver should be both explainable and maintainable.
How Has This Been Tested?
It's lints, so it blocks the CI when things are missing.
Types of changes
Checklist: