Simon Long
Simon Long

Reputation: 1450

Elements not processing event when Material-ui Popup is displayed

I have a simple material-ui List containing ListItem elements.

I want a Popover to appear beside whatever ListItem I place the mouse over. For this I am using the mouseEnter event. In its handler I set the anchor element of the Popover to be the ListItem that the mouse pointer is currently over.

This works fine for the first element which I hover over. However because the Popover is essentially behaving in a "modal" type fashion, when I move to another ListItem in the List its mouseEnter event doesn't get fired.

I've been at this for a few hours now and can't find a way around it ?

Here's a CodeSandbox. Try hovering on one of the ListItems and you'll see output in the console. Try moving to another and nothing happens.

Edit loving-currying-zpw8y

import React, { useState } from "react";
import "./styles.css";
import { List, ListItem, ListItemText, Popover } from "@material-ui/core";

export default function App() {
  const [popoverAnchorElement, setPopoverAnchorElement] = useState(null);
  const handleMouseEnter = event => {
    console.log("onMouseEnter - " + event.currentTarget.textContent);
    setPopoverAnchorElement(event.currentTarget);
  };

  const handleClose = (event, index) => {
    setPopoverAnchorElement(null);
  };

  let isPopoverOpen = Boolean(popoverAnchorElement);
  return (
    <div className="App">
      <List style={{ maxWidth: "100px" }}>
        <ListItem button>
          <ListItemText onMouseEnter={handleMouseEnter}>ListItem1</ListItemText>
        </ListItem>
        <ListItem button>
          <ListItemText onMouseEnter={handleMouseEnter}>ListItem2</ListItemText>
        </ListItem>
        <ListItem button>
          <ListItemText onMouseEnter={handleMouseEnter}>ListItem3</ListItemText>
        </ListItem>
      </List>
      <Popover
        open={isPopoverOpen}
        onClose={handleClose}
        anchorEl={popoverAnchorElement}
        anchorOrigin={{
          vertical: "top",
          horizontal: "center"
        }}
        transformOrigin={{
          vertical: "top",
          horizontal: "left"
        }}
      >
        <ListItem button>
          <ListItemText>ListItemInPopover</ListItemText>
        </ListItem>
      </Popover>
    </div>
  );
}


Upvotes: 1

Views: 1153

Answers (1)

tmdesigned
tmdesigned

Reputation: 2254

The Popover component overlays the whole screen (position:fixed; left:0; top:0; right:0; bottom:0; z-index:1300), effectively blocking any mouse events from lower items.

You could try to circumvent this, for instance adding pointer-events:none; to its overlay element would allow cursor events to pass through it.

But, using a component that blocks the whole viewport just for a small menu item seems odd to me and is likely an uphill battle.

There is a similar component in the same library called Popper, which probably is more suited to your needs. Here you can see I've converted your Popover to a Popper and you get results a little more like what you're expecting. (Note I added some CSS to this element in the code sandbox to make it clearer.)

  <Popper
    open={isPopoverOpen}
    onClose={handleClose}
    anchorEl={popoverAnchorElement}
    className="popper-item"
  >
    <ListItem button>
      <ListItemText>ListItemInPopover</ListItemText>
    </ListItem>
  </Popper>

https://codesandbox.io/s/keen-smoke-x8tu7

I will note that the documentation points out that Popper will not automatically close if you click away from these items, but that this can be added.

You might also look into the MenuList component which uses Popper under the hood but also handles some state for you.

Upvotes: 1

Related Questions