[UEPR-483] "Choose a Sprite" and "Choose a Backdrop" keyboard accessibility#433
Conversation
e37597f to
f2902ce
Compare
packages/scratch-gui/src/components/action-menu/action-menu.jsx
Outdated
Show resolved
Hide resolved
packages/scratch-gui/src/components/action-menu/action-menu.jsx
Outdated
Show resolved
Hide resolved
packages/scratch-gui/src/components/action-menu/action-menu.jsx
Outdated
Show resolved
Hide resolved
packages/scratch-gui/src/components/action-menu/action-menu.jsx
Outdated
Show resolved
Hide resolved
packages/scratch-gui/src/components/action-menu/action-menu.jsx
Outdated
Show resolved
Hide resolved
packages/scratch-gui/src/components/action-menu/action-menu.jsx
Outdated
Show resolved
Hide resolved
packages/scratch-gui/src/components/action-menu/action-menu.jsx
Outdated
Show resolved
Hide resolved
KManolov3
left a comment
There was a problem hiding this comment.
Looks mostly good, left a comment on an edge case. Thanks for migrating the action menu to React hook syntax!
packages/scratch-gui/src/components/action-menu/action-menu.jsx
Outdated
Show resolved
Hide resolved
| }, CLOSE_DELAY); | ||
| }, []); | ||
|
|
||
| const clickDelayer = useCallback( |
There was a problem hiding this comment.
This looks like it slightly differs in behavior from production:
- on production, when we open and close the sprite modal, the action menu is closed
- with this change, when we open and close the sprite modal, the action menu is still open
I am not averse to the updated behavior, as it aligns with the "return focus to previously selected element when you navigate out of a modal".
However there are some visually unpleasant cases:
- if I open the "Upload a sprite" menu from the action button, the menu closes after a timeout, but if I navigate out of the upload dialog which it opens, it reopens the menu, but the label shows on the bottom
- same for other actions
I am open to suggestions for what the most consistent behavior (and the least effort change) would be.
As a fallback, keeping the production behavior (and possibly making sure the inner menu items are also unselected, so that no inconsistent label appears) can be an option for this case (so, blur out of the focused action menu, but keep the focus, so that TAB would return to the same / next item).
There was a problem hiding this comment.
Additionally, the behavior when clicking "Surprise" has changed here - it unfocuses the action menu entirely, while on production it blurs, but keeps the focus on the menu item.
There was a problem hiding this comment.
For the first comment, I have added a timer that blurs and refocuses on the menu item so to avoid the visual unpleasantries of the positioning of the tooltip upon expansion (the issue was that it needed time to expand so when it refocused the menu was not open yet and the tooltip got stuck in the middle of the core button and the right one)
There was a problem hiding this comment.
For the second comment I altered the behavior of the former clickDelayer and removed all the unfocus logic since it came from the idea of closing down the menu upon click which we don't want anymore. This, in my opinion, remains more consistent with the idea of keeping focus on the selected item after its effect has been fulfilled, that we have implemented so far in the accessibility tasks.
What do you think @KManolov3? cc: @adzhindzhi
There was a problem hiding this comment.
FYI, we still have an issue related to the first case. If you select Choose a Sprite, then close the modal, the tooltip is displayed twice - once for the main button and once for the Choose a Sprite item in the menu.
Regarding the clickDelayed issue, I don't have a strong opinion, but I think the current production behavior, where the menu closes on click while focus remains on the main button, feels more convenient than keeping the menu open. That said, I can see benefits to both approaches.
In general, the behavior when clicking on menu items feels a bit inconsistent right now. For example:
- For
SurpriseandPaint, the menu stays open and the selected item remains focused. - For
Choose a SpriteandUpload, the menu closes, and when the modal is closed, the menu is re-opened and the main button is focused (and in the case ofChoose a Sprite, two tooltips are shown).
It might be better to standardize this behavior across all menu items. For example, the menu could always close while keeping focus on the main button, or we could choose another consistent option if this one doesn't make sense or introduces technical complications. What do you think?
|
The latest commit fixes the following 3 bugs that existed:
What I did was remove onBlur logic and replace it in the following way - onBlur unites a few of the following cases:
|
KManolov3
left a comment
There was a problem hiding this comment.
Left a few minor comments, but otherwise the behavior looks very smooth to me now! 🙌
There's a lot of logic "under the hood" which may end up being finicky, but hopefully this doesn't end up getting changed very often.
| } else if (e.key === KEY.TAB) { | ||
| setIsExpanded(false); | ||
| focusItem(buttonRef.current); | ||
| } else if (e.key === KEY.ESCAPE) { |
There was a problem hiding this comment.
I see some possibly unintended behavior when clicking ESCAPE, after which attempting to TAB- I need to TAB twice for something to happen. It's more of a corner case, but might be worth fixing if it isn't too hard. Otherwise I am fine with leaving as is for now.
There was a problem hiding this comment.
Hmm, it seems to be another issue that appears on firefox but not chrome. Upon reconsideration, I am not sure if Escape behavior is something we want at all here. I mean there are other intuitive ways to focus away as a keyboard or mouse user, such as tab or clicking outside of the menu. What do you think?
There is the "we want to be able to focus the core option" argument but the bottom one already duplicates that behavior on every use of action menu.
A compromise would be "focus on the main button on escape but keep the menu open, since we can still enter it with arrows". Collapsing seems a little unnatural to me now.
packages/scratch-gui/src/components/action-menu/action-menu.jsx
Outdated
Show resolved
Hide resolved
| }), [] | ||
| ); | ||
|
|
||
| const handleItemMouseEnter = useCallback(index => () => { |
There was a problem hiding this comment.
Can you leave a comment why this is needed?
packages/scratch-gui/src/components/action-menu/action-menu.jsx
Outdated
Show resolved
Hide resolved
packages/scratch-gui/src/components/action-menu/action-menu.jsx
Outdated
Show resolved
Hide resolved
packages/scratch-gui/src/components/action-menu/action-menu.jsx
Outdated
Show resolved
Hide resolved
| @@ -222,12 +196,10 @@ const ActionMenu = ({ | |||
|
|
|||
| const handleClick = useCallback(e => { | |||
There was a problem hiding this comment.
Having a useCallback inside of a map is an antipattern - https://react.dev/reference/rules/rules-of-hooks#only-call-hooks-at-the-top-level. We should be able to extract this on top level.
Resolves
https://scratchfoundation.atlassian.net/browse/UEPR-483
Proposed Changes
Reason for Changes
Part of accessibility initiative for Scratch.