material-ui
material-ui copied to clipboard
[a11y] Not keyboard accessible for components inside `MenuItem`
Duplicates
- [X] I have searched the existing issues
Latest version
- [X] I have tested the latest version
Steps to reproduce 🕹
Link to live example: https://codesandbox.io/s/beautiful-voice-bfgjc9
Steps:
- Tab into menu and hit the "Enter" button
- Hit the "down arrow" button until you arrive at the slider/switch
- Hit "Enter"/"Space" button(s) to focus on slider/switch
Current behavior 😯
The slider/switch will not focus, preventing users from manipulating the input with their keyboard.
Expected behavior 🤔
The slider/switch should focus, allowing users to manipulate the input with their keyboard.
Context 🔦
Allow our keyboard users to manipulate menu input.
Your environment 🌎
npx @mui/envinfo
System:
OS: macOS 12.6.1
Binaries:
Node: 14.18.3 - ~/.nvm/versions/node/v14.18.3/bin/node
Yarn: 1.22.19 - ~/.nvm/versions/node/v14.18.3/bin/yarn
npm: 8.1.2 - ~/Projects/vt-llp-ui/node_modules/.bin/npm
Browsers:
Chrome: 107.0.5304.121 <= current browser
Edge: Not Found
Firefox: 107.0
Safari: 16.1
npmPackages:
@emotion/react: 11.10.0 => 11.10.0
@emotion/styled: 11.10.0 => 11.10.0
@mui/base: 5.0.0-alpha.94
@mui/core-downloads-tracker: 5.10.13
@mui/material: 5.10.2 => 5.10.2
@mui/private-theming: 5.10.9
@mui/styled-engine: 5.10.8
@mui/system: 5.10.13
@mui/types: 7.2.0
@mui/utils: 5.10.9
@types/react: 17.0.38 => 17.0.38
react: 17.0.2 => 17.0.2
react-dom: 17.0.2 => 17.0.2
typescript: 4.6.4 => 4.6.4
Thanks for reporting this. It's a similar issue to what's described in https://github.com/mui/material-ui/issues/33268. We'll look into supporting such scenarios in MUI Base's Menu (which will be used by the Material UI's one in the future).
If, however, someone from the community would like to take a stab at fixing it in the current version of Material UI, I'm happy to discuss it and review a PR.
@ber8749 i'm not sure if it's possible to focus elements inside MenuItem natively by library, but there is a workaround to focus Switch element inside MenuItem
<MenuItem onFocus={(e) => ref.current.focus()}>
<Switch inputRef={ref} defaultChecked />
</MenuItem>
Thanks for reporting this. It's a similar issue to what's described in #33268. We'll look into supporting such scenarios in MUI Base's Menu (which will be used by the Material UI's one in the future).
If, however, someone from the community would like to take a stab at fixing it in the current version of Material UI, I'm happy to discuss it and review a PR.
@michaldudak i did some digging, as far as i understood it's not possible to automatically detect which element user want to focus with exsisting props. So i'm thinking a new prop transferFocusTo which accepts dom element, can be passed to MenuItem might solve the issue, so when ever MenuItem is focused if that MenuItem also has transferFocusTo prop, we will focus element passed in transferFocusTo prop too
This might be how Api look .
Api:
<MenuItem transferFocusTo={ref.current}>
<Switch defaultChecked inputRef={ref} />
</MenuItem>
Implementation:
<MenuItemRoot
ref={handleRef}
role={role}
onFocus={(e) => {
if (transferFocusTo) {
transferFocusTo.focus();
}
handleFocus(e);
}}
tabIndex={tabIndex}
component={component}
focusVisibleClassName={clsx(classes.focusVisible, focusVisibleClassName)}
className={clsx(classes.root, className)}
{...other}
ownerState={ownerState}
classes={classes}
/>
If you are fine with proposal i'm happy to create PR
After discussing it internally with the team and reading through ARIA specs, I started to think it may not be the best idea to allow all interactive elements within menus. Sliders, for example, are controlled by arrow keys and will interrupt the normal flow of highlighting menu items when focused. Sliders with multiple thumbs present an even more significant challenge.
Switches, on the other hand, should present no such problems. ARIA defines the menuitemcheckbox role (https://w3c.github.io/aria/#menuitemcheckbox), which we could use here. So technically, it will be a checkbox, but it could be styled as a switch. We can create a MenuItemCheckbox component with such functionality.
@ber8749 i'm not sure if it's possible to focus elements inside MenuItem natively by library, but there is a workaround to focus Switch element inside MenuItem
<MenuItem onFocus={(e) => ref.current.focus()}> <Switch inputRef={ref} defaultChecked /> </MenuItem>
@sai6855 Thank you, this was quite helpful. Do you know of a similar workaround for the Slider component?
@ber8749
<MenuItem onFocus={() => ref.current.focus()}>
<Slider slotProps={{ input: { ref } }} aria-label="Volume" />
</MenuItem>
@ber8749 i'm not sure if it's possible to focus elements inside MenuItem natively by library, but there is a workaround to focus Switch element inside MenuItem
This solution makes the menu inaccessible. For example, the arrow keys do not work correctly.
Relevant discussion on the W3C github:
- https://github.com/w3c/aria/issues/1587