Keyboard navigation (accessibility) with ant design- SubMenu - reactjs

I need to make my site accessible. I'm using ant-design Menu, and the Menu.Submenu is not keyboard accessible, i believe. By adding tabindex i can tab to the submenu, but clicking ENTER nothing happens- the submenu doesn't open, i have no way of programatically openning it.
Under handleKeyPress i'm able to register the ENTER click event on the submenu title but i cant get the submenu to open and show the items. Is there functionality for that?
Perhaps there's a way and i'm missing something?
<Menu.SubMenu onKeyPress={(event) => this.handleKeyPress(event,
"EditYourProfileSubMenu")} onTitleClick={()=>{alert('title clicked')}}
tabIndex={0} title="Edit Your Profile" style={{ color: 'white' }}>
It would be very nice to have an entire Menu which is keyboard accessible, including navigation with arrows and automatic enter click triggers click events.
But i'll also be happy with a way to programatically open ant design SubMenu.

I'm still waiting for a better solution, maybe someone will reply to
https://github.com/ant-design/ant-design/issues/14356
I found a meantime hacky solution for this- using Menu's openKeys prop(see https://ant.design/components/menu/). It gets an array of submenu keys to determine which are open. So using onKeyDown i listened to these events and added/removed the right submenu key from the array (using State, of course).
<Menu
openKeys={this.controller.getMainMenuOpenKeys()}
...>
...
<Menu.SubMenu key={"EditYourProfileSubMenu"}
onKeyDown={(event) => this.handleKeyPress(event, "EditYourProfileSubMenu", true)}
onTitleClick={() => {
this.controller.setMainMenuOpenKeys(["EditYourProfileSubMenu"]) }} //sets the state which openKeys listens to
tabIndex={0}
title="Edit Your Profile" style={{ color: 'white' }}>
...
</Menu.SubMenu>
</Menu>
Adding openKeys field to menu messes with the mouse click flow, so i had to add onTitleClick and add the key to openKeys there also.

Related

Material UI: not able to interact with the background elements when the MUI Dialog is open

I'm working on a Chatbox styling using MUI and I've a issue. I'm not able to interacting with the background elements when the Dialog is open. I'm only able to click on the Dialog content but not able to click on the background Form Component.
herer is he codesandbox link :
https://codesandbox.io/s/stupefied-snowflake-jolyw7?file=/src/components/Chatbox.js
in the Console I Change the z-index to 1 it worked but not able to interact with the foreground component that is chatbox.
You have to first close the modal then you would be able to make any changes in the background form.
Checked your code and found that outside click is not working the modal is is not hiding , with this you're unable to use the form.
change Dialog material UI to this :
<Dialog
disableScrollLock
disableEnforceFocus
hideBackdrop
onClick={handleClose}
aria-labelledby="customized-dialog-title"
open={open}
transitionDuration={{ enter: 500, exit: 500 }}
// scroll="body"
sx={{
paddingLeft: "50%"
}}
>
With this when you click in background form element , First the modal pop up will close and then you can make changes in the form.
Hope this helps !

React.js Map Array style for a unique id and each button disabled

I need each question button when it is clicked to be disabled. I would also like to style each question button. I already looked for several answers to this problem but I found nothing. As I don't know much about React in this case, should I use useEffect or children.props? If you have any solution please let me know.
Demo
Your buttons' state is already available for each button, you just need to use state and disable button.
{/* Question buttons */}
{buttons.map((button) => (
<button key={button.id} disabled={button.clicked} onClick={() => buttonClickHandler(button.id)}>
{button.label}
</button>
))}
About styling buttons individually, you can create a className for each button and style buttons depending on that:
<button className={'button-' + button.id}>
and now from css apply color:
.button-01 { background: pink; }
The second approach could be that you create styles for each button inside the state, and consume it from there.
<button style={button.style}>

How do you close the material UI context menu, without displaying the default context menu?

I am trying to use the material UI menu to display a context menu on a div, as in https://material-ui.com/components/menus/#context-menu
This works I can right-click and it displays.
However, the material-ui context menu when displayed injects a transparent div covering the whole screen behind the menu. This means any further clicks are intercepted by this element. It seems this element will close the menu when a left click is detected but will move and continue displaying the same context menu if you right-click anywhere else on the page, including where the context menu is irrelevant.
Is there any way to display the menu without this transparent div which is removing control from my page?
You can see this action in the example: https://material-ui.com/components/menus/#context-menu
Right-click on the text, then right-click anywhere else (while the menu is still displayed) and you can trigger the menu to appear all over the page, even in the app bar, where the menu options make no sense.
I tried to do it in like this:
export default function MenuPopupState() {
return (
<PopupState variant="popover" popupId="demo-popup-menu">
{popupState => {
const menuProps = bindMenu(popupState);
return (
<React.Fragment>
<Button
variant="contained"
color="primary"
{...bindTrigger(popupState)}
>
Open Menu
</Button>
<Menu
{...menuProps}
onContextMenu={event => {
event.preventDefault();
}}
onMouseDown={e => {
menuProps.onClose();
}}
>
<MenuItem onClick={popupState.close}>Cake</MenuItem>
<MenuItem onClick={popupState.close}>Death</MenuItem>
</Menu>
</React.Fragment>
);
}}
</PopupState>
);
}
https://codesandbox.io/s/material-demo-szpbr?file=/demo.js

Material UI: Popover breaks when using onMouseLeave prop

I remade the simple popover example on this page except using mouse hover props:
https://codesandbox.io/s/eager-dewdney-yt3v-yt3vb
<Button
variant="contained"
onMouseEnter={e => setAnchorEl(e.currentTarget)}
// onMouseLeave={() => setAnchorEl(null)}
>
As soon as onMouseLeave is uncommented the above code sandbox will break silently. The UI will appear fine but the popover will not display. I have found the same to happen in my actual project.
Commenting onMouseLeave will at least allow onMouseEnter to work correctly with the popover, but it is then stuck on screen.
Am I not using onMouseLeave correctly here?
If it is being used correctly but appears to be a library related bug, what mouse based alternative could be used in place of onMouseLeave above?
I ran into the same issue, and I did not want to use a Tooltip.
The fix is to add a style to the popup to suppress the additional onMouseLeave() event that gets fired right after the popup opens:
<Popover
style={{ pointerEvents: 'none' }}
>
{children}
</Popover>
I found the fix here.

How to make a react bootstrap dropdown with panelgroups

I am trying to make a dropdown where each menuitem will have submenuitems
as
Drodown(select)
1. List item(header)
Litem-1(subheader)
Litem-2(subheader)
2. Header-2(header)
Litem-2-1(subheader)
Litem-2-2(subheader)
I am using react bootstrap dropdown to achieve this
where each menuitem would have a panelgroup of items as Litem-1 and Litem-2
So When i click on select the dropdown should open up, but when i click on individual headers(which are not expanded by default), should expand and should not close the dropdown and when clicked on subheaders dropdown has to be closed
I have tried using open option of dropdown ,using this i am trying to control the visibility of the dropdown i could achieve the same for headers when i try to do the same i could not achieve because the event is bubbling up till the parent and dropdown remains open , i also tried to use stopPropagation but looks like menuitem is not respecting it not sure why it is the case
I tried to solve this as this
https://codepen.io/anon/pen/WONMGd
can some one please comment if this approach is right and also why cannot I use event.stopPropagation and prevent default here
Thanks
To use panels in the way you sort of want them to you have to set the accordion prop on your panel to be true. Check out the code below:
<Dropdown.Menu className="Groups" bsRole="menu">
<MenuItem onClick={this.menuItemClickedThatShouldntCloseDropdown.bind(this)}>
<PanelGroup activeKey="1" accordion activeKey={this.state.activeKey}>
<Panel header="header1" eventKey='1'>
<span onClick={this.menuItemShouldCloseDropDown.bind(this)}>Content-1</span>
</Panel>
<Panel header="header2" eventKey='2'>
<span onClick={this.menuItemShouldCloseDropDown.bind(this)}>content=2</span>
</Panel>
</PanelGroup>
</MenuItem>
<MenuItem onClick={this.menuItemClickedThatShouldntCloseDropdown}>
hi
</MenuItem>
</Dropdown.Menu>
</Dropdown>
and add this to your class definition:
handleSelect(activeKey) {
this.setState({ activeKey })
}
This seems to solve at least one of your problems. Id recommend tearing out the other pseudo-state this._forceOpen logic to see what you really need.

Resources