Search code examples
material-uipopover

How to change a position of the Popover component as part of the Select component in MUI 5?


I use a Select component (assumethis one). By default, a Popover component appears just under the select field, but I want to place it on the right side. I'll describe below the ways I tried to achieve this behavior and how I failed every time. Keep in mind that I'm a newbie to the MUI.

  1. The most proper way to change the position is to set up anchorOrigin and transformOrigin props, but it works only if you can access those props. The Select component makes the Popover on its own (or more precisely, a Menu component inside the Select) and doesn't provide an API to propagate props.

  2. The Menu component has a PopoverClasses prop that propagates classes to the Popover, so I wanted to change position by overriding left and top styles with values calculated by JS. But no matter how hard I tried to figure out how it worked, I couldn't. Every guide I found uses makeStyles from "@mui/styles" or createUseStyles from "react-jss" which are deprecated since MUI v5. Is classes prop totally deprecated in MUI v5?

  3. Adding styles like "& .MuiPopover-root" to Select or Menu didn't work too, because the Popover creates near the top of the DOM to work as a modal dialog and isn't a child of the Select.

  4. Despite the Menu doesn't propagates props to the Popover directly, it propagate props to a MenuList which is a child of the Popover. Using MenuListProps: {ref=myRef} I can access to the DOM element of the Popover by myRef.current.parentElement. But it isn't enough, because I have no good event to override values. The Popover is created after a short period of time after an onOpen event fires of the Select, so during the event a value myRef.current is undefined, and after setTimeout() is too late - it's noticeably how Popover jumps.

It's too hard for such a simple action. Did I miss something obvious?


Solution

  • Using Select component you can propagate its Popover props through the MenuProps property.

    It works because Menu actually propagates props to Popover and can accept all its properties, as described in docs

    Example:

    <Select
      labelId="demo-simple-select-label"
      id="demo-simple-select"
      value={age}
      label="Age"
      onChange={handleChange}
      MenuProps={{
        anchorReference: "anchorPosition",
        anchorPosition: { top: 0, left: 475 }
      }}
    >
      <MenuItem value={10}>Ten</MenuItem>
      <MenuItem value={20}>Twenty</MenuItem>
      <MenuItem value={30}>Thirty</MenuItem>
    </Select>