Material-ui: open menu by event hover
Asked Answered
B

4

15

Currently the menuItem only opens your children after a click. Is there an attribute that I agree to open via Hover?

<MenuItem key={index}
  menuItems={menuitems}
  **onHover={true}**
>
 menuItem
</MenuItem>
Bendicty answered 15/12, 2017 at 12:59 Comment(2)
Use this: jcoreio.github.io/material-ui-popup-stateWarfourd
Checkout this answer, had the same problem and it worked for me: https://mcmap.net/q/593490/-how-to-make-material-ui-menu-based-on-hover-not-clickLagrange
A
16

There is not specific attribute available through the material-ui library. However, you could create this yourself pretty easily using the onMouseOver event.

I've adapted the Simple Menu example from the material-ui site to show you how this can be done:

import React from 'react';
import Button from 'material-ui/Button';
import Menu, { MenuItem } from 'material-ui/Menu';

class SimpleMenu extends React.Component {
  state = {
    anchorEl: null,
    open: false,
  };

  handleClick = event => {
    this.setState({ open: true, anchorEl: event.currentTarget });
  };

  handleRequestClose = () => {
    this.setState({ open: false });
  };

  render() {
    return (
      <div>
        <Button
          aria-owns={this.state.open ? 'simple-menu' : null}
          aria-haspopup="true"
          onClick={this.handleClick}

          { // The following line makes the menu open whenever the mouse passes over the menu }
          onMouseOver={this.handleClick}
        >
          Open Menu
        </Button>
        <Menu
          id="simple-menu"
          anchorEl={this.state.anchorEl}
          open={this.state.open}
          onRequestClose={this.handleRequestClose}
        >
          <MenuItem onClick={this.handleRequestClose}>Profile</MenuItem>
          <MenuItem onClick={this.handleRequestClose}>My account</MenuItem>
          <MenuItem onClick={this.handleRequestClose}>Logout</MenuItem>
        </Menu>
      </div>
    );
  }
}

export default SimpleMenu;
Averett answered 16/12, 2017 at 18:10 Comment(6)
My problem is that I want the menu to disappear if the mouse leaves that area, so I tried onMouseOut and onMouseLeave to close the menu but it seems that when this option is there the menu never opens! But when I remove the onMouseOver or Leave then it works fine but just stays there if you don't click something.Unclassified
@StazChristo Was having the same issue, found a solution MenuListProps={{ onMouseLeave: handleClose }} hereTamatave
@StazChristo That happens because when you open the menu, a modal layout is placed over the whole page, that means the onMouseLeave event will be fired immediately after onMouseEnter. devonj's solution is good, but for it to work you must change the menu anchor so that it covers the button in its entirety.Functionary
Looks like the link is a fake link. Beware.Geter
@Geter this is quite an old answer, looks like the link went stale. Updated to the new valid doc site.Averett
MVP MVP TY! I was sooo confused when I clicked it and my screen filled up with 100 pop-up windows with spam.... haven't seen a site like that since the early 2000s.Geter
L
5

I got it to work by upping the z-index of the button. Otherwise, the mouse technically goes out of the button when the modal appears on top of the button. Then the menu will close since the user is no longer hovering.

If you add onMouseLeave to Menu then onMouseLeave will only trigger if you go out of the browser. So instead, I added onMouseLeave to MuiList which doesn't take up the whole page.

I also added need some extra conditionals in the handleOpen to account for if the mouse leaves the button but enters the menu.

import React, { useState } from "react";
import Button from "@material-ui/core/Button";
import Menu from "@material-ui/core/Menu";
import { createMuiTheme, ThemeProvider } from "@material-ui/core/styles";
const theme = createMuiTheme({});
const MyMenu = () => {
  const [anchorEl, setAnchorEl] = useState(null);
  const [open, setOpen] = useState(false);

  const handleOpen = (event) => {
    setAnchorEl(event.currentTarget);
    setOpen(true);
  };

  const handleClose = (e) => {
    if (e.currentTarget.localName !== "ul") {
      const menu = document.getElementById("simple-menu").children[2];
      const menuBoundary = {
        left: menu.offsetLeft,
        top: e.currentTarget.offsetTop + e.currentTarget.offsetHeight,
        right: menu.offsetLeft + menu.offsetWidth,
        bottom: menu.offsetTop + menu.offsetHeight
      };
      if (
        e.clientX >= menuBoundary.left &&
        e.clientX <= menuBoundary.right &&
        e.clientY <= menuBoundary.bottom &&
        e.clientY >= menuBoundary.top
      ) {
        return;
      }
    }

    setOpen(false);
  };

  theme.props = {
    MuiList: {
      onMouseLeave: (e) => {
        handleClose(e);
      }
    }
  };
  return (
    <div>
      <ThemeProvider theme={theme}>
        <Button
          id="menubutton1"
          aria-owns={open ? "simple-menu" : null}
          aria-haspopup="true"
          onMouseOver={handleOpen}
          onMouseLeave={handleClose}
          style={{ zIndex: 1301 }}
        >
          Open Menu
        </Button>
        <Menu
          id="simple-menu"
          anchorEl={anchorEl}
          open={open}
          anchorOrigin={{
            vertical: "bottom",
            horizontal: "center"
          }}
          transformOrigin={{
            vertical: "top",
            horizontal: "center"
          }}
        >
          Menu
          <br />
          Items
        </Menu>
      </ThemeProvider>
    </div>
  );
};

export default MyMenu;

CodeSandbox

Low answered 26/4, 2021 at 2:13 Comment(0)
X
2

I have added mouseLeave listener on container div to close the menu, and mouseOver listener on menu button to open menu. This worked for me...

<div onMouseLeave={closeMenu}>
 <button onMouseOver=(openMenu) />
 <Menu />
 <MenuItems />
</div>
Xhosa answered 16/2, 2022 at 15:34 Comment(0)
H
1

This is how I did it:

https://codesandbox.io/s/mui-menu-hover-to-show-dropdown-iguukw?file=/src/TopMenu.tsx

I used on onMouseLeave and onMouseEnter events to control when to show and hide the dropdown menus.

I also used a string state to determine which dropdown menu should show. Only one dropdown menu should show at one moment of time.

Hintz answered 25/11, 2022 at 20:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.