-
Notifications
You must be signed in to change notification settings - Fork 54
[Accessibility] Adds built-in support for Screen Reader announcements #51
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
Conversation
…d adding autoselect support
afe1e48
to
9d1a19d
Compare
I see the Action only defines Ubuntu and MacOS -- let me know if I should be adding Windows or if the settings should be updated to not require Windows. |
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.
Hey @inkblotty, I'm happy to get a chance to see some of your work! I dropped some comments, but overall this seems like it's headed in a good direction. Thanks for making this component more accessible!
src/autocomplete.ts
Outdated
this.feedback.innerHTML = getAnnouncementStringByEvent(input) | ||
this.container.dispatchEvent(new CustomEvent('sr-update')) | ||
} | ||
}, 100) |
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.
Would you mind detailing why we need the timeout, and why 100
was chosen? I'm guessing it's an order-of-events issue, but those can usually be solved with 0
timeout.
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 suspect this will change after our screenreader auditors interact with it, but it allows time for the announcements of other events to finish. If "polite" is used instead, VoiceOver ignores the announcement half the time.
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 actually got me thinking about how we'll test with our auditors. Little change incoming.
src/autocomplete.ts
Outdated
@@ -101,6 +143,15 @@ export default class Autocomplete { | |||
} | |||
} | |||
|
|||
updateFeedbackForScreenReaders(input: ScreenReaderAccouncementConfig): void { |
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 the DRY approach here, making it easy to update the sr announcment. I wonder if it would be simpler to just pass a string into here, and remove the ScreenReaderAccouncementConfig
input type. That way calling sites could just call the exact function they need to get the string and pass it in, rather than having different event
types with various options. WDYT?
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 see what you're saying. I opted for this approach because of the "new-options" event having two different types of announcements, depending on if autoselect is enabled or not. It seemed like it would get messy to keep all the different combinations of strings in autocomplete.ts when it could be in its own file.
However, I could rewrite it to be an additional function, remove the events, and call "newOptionsWithAutoselect" or something. WDYT?
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 think that would probably be an easier approach to maintain 👍
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.
Ok please let me know what you think of the new approach @dgreif 🙏
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.
It would be great if we can include these new events and markup in the README.
- Note the ID is the same as the <ul> with "feedback" appended | ||
- Also note that aria attributes will be added programmatically if they aren't set correctly | ||
--> | ||
<div id="items-popup-feedback" class="sr-only"></div> |
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.
What does sr-only
do? It seems unused to me.
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.
It doesn't do anything in the example except suggest to use a screen reader only
class. In dotcom, this class is sr-only
. I could add a note or remove if it's confusing. WDYT?
Co-authored-by: Kristján Oddsson <[email protected]>
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 new comment, but I think you addressed the rest of my feedback. I'll defer to @koddsson for final approval as he knows this repo better than I do 😄
* Add missing `package-lock.json` file * Inline all the screen reader announcements By inlining the screen reader announcement text we remove a layer of indirection. * Replace `sr-update` event dispatch with a MutationObserver The event fired has no effect in production which indicates that it shouldn't be in the code at all. What we want to do in the tests is to wait for the feedback element to have text so we should instead use a MutationObserver to wait for the element to change before running our assertion. * Inline listbox ID in tests We remove a level of indirection by inlining the list box ID. It's more apparent to the reader of the tests what elements are being referred to without having to find the definition of the `listboxId` variable.
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.
Looks good to me 👍🏻
Summary
New Features
If
data-autoselect
is "true" on theauto-complete-element
, pressing the "Enter" key will select the first option available, even if the input is focused and not the first option.Reference Slack thread on this established pattern which describes that Primer React has already established the pattern of using "Enter" to commit the first suggestion in SelectPanel.
Accessibility
If a
<listbox_id>-feedback
element is detected, the following screen-reader updates are announced:data-autoselect
is true)Some set up work was also done for client-side options, but that work will be tackled whenever #52 is prioritized.
cc @github/accessibility