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
Improving usability on onboarding screen when using keyboard and screen reader #10661
Improving usability on onboarding screen when using keyboard and screen reader #10661
Conversation
| @@ -246,7 +246,7 @@ | |||
| } | |||
| // modal overflow scrolling | |||
| .onboarding-modal-scroll-container { | |||
| height: calc(100vh - 289px); | |||
| height: calc(100vh - 332px); | |||
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.
Since it was causing two scrollbars I changed it to so that it has only one scrollbar
| import { createFocusTrap } from 'focus-trap'; | ||
| import { defaultChildrenPropTypes } from '../../common-prop-types'; | ||
|
|
||
| const FocusTrap = ({ selector, children }) => { |
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 created this wrapper component that uses library 'focus-trap' to trap focus. Ideally I love to convert it to a hook rather than a component but since it is used by class components too it can't be a hook.
| import PropTypes from 'prop-types'; | ||
| import { h, Fragment } from 'preact'; | ||
| import { useEffect, useRef } from 'preact/hooks'; | ||
| import { createFocusTrap } from 'focus-trap'; |
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 added this library https://bundlephobia.com/result?p=focus-trap@6.1.2 It's size is 2.3kb minified and gzipped (but should be much smaller since I don't use all functionality of that lib and it is tree shakabale) is this ok?
| }; | ||
|
|
||
| FocusTrap.defaultProps = { | ||
| selector: '.crayons-modal', |
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 made the default selector value '.crayon-modal' since this component will be mostly be used by modals (rarely in other places where different selector string could be passed)
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.
If you open a second modal over the top of an existing one I think the tabbing will be locked to the first.
That being said I believe, with how you've set it up, you can do some something like
<FocusTrap selector={reference.current}>
<div id="locked-in" ref={reference}></div>
</FocusTrap>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.
Ref would work too. Incase modal appears another modal it can pass another selector string like id of the modal and it would also work.
<FocusTrap selector="#secondModal">
<div id="secondModal">
second modal
</div>
</FocusTrap>
But on the other hand nested modals might not be used anywhere (but I could be wrong). Having no prop needed to be passed for this component by default makes API much simpler.
| </h2> | ||
| </header> | ||
| <div className="onboarding-modal-scroll-container"> | ||
| <ul data-testid="onboarding-tags" className="onboarding-tags"> |
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 changed div to ul and li so that I could be read by screen reader
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.
Haven't reviewed the code but I wonder if we can improve the behavior in the third slide
I have to tab 3 times before I can press space to select the "follow" button:
It seems to work nice otherwise. There are a few violations found in the Accessibility panel in Firefox but I think they are beyond the objective of this PR.
Thanks @Rafi993!
|
FocusTrap would be useful for #10610 too. |
| import { createFocusTrap } from 'focus-trap'; | ||
| import { defaultChildrenPropTypes } from '../../common-prop-types'; | ||
|
|
||
| const FocusTrap = ({ selector, children }) => { |
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.
Is it worth having a bool active prop?
Meaning in the future we could add the ability to lock focus if we want to,
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.
Thank you @Link2Twenty. I think boolean active can be added to FocusTrap component and made optional value with default value being true. But right now it is not used here but it could be added later to the component if needed without affecting existing code.
Thank you @rhymes. When "follow" button is selected focus is jumping to the previous element causing this issue. Let me search for reason it is happening. |
Similar issue is also happening in tag selection too. I couldn't figure out why it is happening. Any thoughts @forem/oss Thanks for you help |
| > | ||
| {users.map((user) => ( | ||
| <li key={user.name}> | ||
| <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.
I think this button should have tabindex="-1".
I think we only want the follow button to be in the tab order.
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.
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.
Thank you @Link2Twenty. But there is one issue though the screen reader is not reading out items in the list (the name of the user and the description below now) it just says follow. This might cause confusion for users who are using screen readers since they don't know which user did they just followed. I can add aria-label to the follow button saying "Follow Jere Thompson" it will help but it will still miss out the description but I don't know if that is ok. Any thoughts?
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.
When I remove the handler this.handleClick it is not happening I did try adding both event.preventDefault() and event.stopPropagation() they don't seem to affect this. It is something to do with the state change. Let me keep searching.
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 is a bug in the FocusTrap component that is causing this when I remove it is working properly. Let me keep searching further.
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 was able to fix this by moving FocusTrap component one level up to app/javascript/onboarding/Onboarding.jsx there are some tests failing (even though what the test is looking for is working when tested manually) let me fix those too.
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 have fixed the breaking tests too
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.
To answer your comment regarding the button name, @Rafi993, an aria-label would help to uniquely identify the individual follow buttons. That would address some instances of an issue that exists throughout the site where controls are repeated (i.e. "Links with the same name have a similar purpose" in the axe extension).
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.
Thank you @marcysutton I have made the change. I did not know about this before.
I have resolved this now |
|
I think some unrelated test failed. |
|
@Rafi993 the tests are fine, it's Codeclimate complaining :) We should likely ignore it in the context of this PR |
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 looks good, thanks @Rafi993, only a question still on the "follow people slide". Is it possible to go down from "2 tabs + space to select follow" to "1 tab plus space"?
Solution @Link2Twenty suggested above does it #10661 (comment) . But when I was using screen reader it just read out the text in the "Follow" button alone and it did not read the user name or the description below. |
| data-testid="onboarding-user-following-status" | ||
| type="button" | ||
| className="user-following-status" | ||
| aria-pressed={selectedUsers.includes(user)} |
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 would could add
aria-label={`${selectedUsers.includes(user) ? 'Unfollow' : 'Follow'} ${user.name}`}This will tell the screen reader what to read.
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 would be to coincide with the tabIndex 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.
Here would could add
aria-label={`${selectedUsers.includes(user) ? 'Unfollow' : 'Follow'} ${user.name}`}This will tell the screen reader what to read.
But it would miss the description for each user
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 guess the three options are
- We remove something from the tabIndex be it the inner or outer button
- We accept multiple tabs is a thing that people have to deal with
- We wait for A11y: Add keyboard navigation to article feed #10468 and use the useListNavigation hook to add j and k navigation support.
|
I'm looking to give this a review this week. Hacktoberfest was pretty busy. 😅 |
| @@ -155,7 +155,7 @@ | |||
| "@honeybadger-io/webpack": "^1.2.0", | |||
| "@rails/webpacker": "5.2.1", | |||
| "@testing-library/user-event": "^12.1.7", | |||
| "ahoy.js": "^0.3.7", | |||
| "ahoy.js": "^0.3.8", | |||
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.
refactor (blocking): This looks like a bad merge or maybe ensure you have merged latest as this does not appear to be related to the work being done in this PR.
| version "5.4.6" | ||
| resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" | ||
| integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== | ||
| table@^6.0.4: |
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.
refactor (blocking): This looks like a bad merge or maybe ensure you have merged latest as this does not appear to be related to the work being done in this PR.
|
As we discussed on the stream it is better to split this PR into multiple small PR's so that it will be easy to review. I'll start creating separate small PR's. |
|
Closing this PR in favour of smaller PRs that have been raised. |




What type of PR is this?
Description
Improving usability when using keyboard and screen reader
Related Tickets & Documents
Closes #9585
QA Instructions, Screenshots, Recordings
Added tests?
Added to documentation?
What gif best describes this PR or how it makes you feel?