Reference

Popover
A Popover is designed to overlay content on top of another element.
Key information to understand when utilizing the
Popover
component:- The component is constructed upon the
Modal
component. - Unlike the
Popper
component, it prevents scrolling and clicking outside the popover.
Basic Popover
import * as React from 'react'; import Popover from '@mui/material/Popover'; import Typography from '@mui/material/Typography'; import Button from '@mui/material/Button'; export default function BasicPopover() { const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(null); const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => { setAnchorEl(event.currentTarget); }; const handleClose = () => { setAnchorEl(null); }; const open = Boolean(anchorEl); const id = open ? 'simple-popover' : undefined; return ( <div> <Button aria-describedby={id} variant="contained" onClick={handleClick}> Open Popover </Button> <Popover id={id} open={open} anchorEl={anchorEl} onClose={handleClose} anchorOrigin={{ vertical: 'bottom', horizontal: 'left', }} > <Typography sx={{ p: 2 }}>The content of the Popover.</Typography> </Popover> </div> ); }
Anchor playground
Adjust the
anchorOrigin
and transformOrigin
positions using radio buttons. You can also configure the anchorReference
to either anchorPosition
or anchorEl
. When set to anchorPosition
, the component references the anchorPosition
prop instead of anchorEl
, allowing you to customize the popover's position.Mouse hover interaction
This example illustrates how to implement the
Popover
component with mouseenter
and mouseleave
events to create interactive popover behavior.Hover with a Popover.
import * as React from 'react'; import Popover from '@mui/material/Popover'; import Typography from '@mui/material/Typography'; export default function MouseHoverPopover() { const [anchorEl, setAnchorEl] = React.useState<HTMLElement | null>(null); const handlePopoverOpen = (event: React.MouseEvent<HTMLElement>) => { setAnchorEl(event.currentTarget); }; const handlePopoverClose = () => { setAnchorEl(null); }; const open = Boolean(anchorEl); return ( <div> <Typography aria-owns={open ? 'mouse-over-popover' : undefined} aria-haspopup="true" onMouseEnter={handlePopoverOpen} onMouseLeave={handlePopoverClose} > Hover with a Popover. </Typography> <Popover id="mouse-over-popover" sx={{ pointerEvents: 'none' }} open={open} anchorEl={anchorEl} anchorOrigin={{ vertical: 'bottom', horizontal: 'left', }} transformOrigin={{ vertical: 'top', horizontal: 'left', }} onClose={handlePopoverClose} disableRestoreFocus > <Typography sx={{ p: 1 }}>I use Popover.</Typography> </Popover> </div> ); }
Virtual element
The
anchorEl
prop can reference a virtual DOM element. You must provide an object adhering to the following interface:interface PopoverVirtualElement { nodeType: 1; getBoundingClientRect: () => DOMRect; }
Select a portion of the text to trigger the popover:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ipsum purus, bibendum sit amet vulputate eget, porta semper ligula. Donec bibendum vulputate erat, ac fringilla mi finibus nec. Donec ac dolor sed dolor porttitor blandit vel vel purus. Fusce vel malesuada ligula. Nam quis vehicula ante, eu finibus est. Proin ullamcorper fermentum orci, quis finibus massa. Nunc lobortis, massa ut rutrum ultrices, metus metus finibus ex, sit amet facilisis neque enim sed neque. Quisque accumsan metus vel maximus consequat. Suspendisse lacinia tellus a libero volutpat maximus.
import * as React from 'react'; import Popover, { PopoverProps } from '@mui/material/Popover'; import Typography from '@mui/material/Typography'; import Paper from '@mui/material/Paper'; export default function VirtualElementPopover() { const [open, setOpen] = React.useState(false); const [anchorEl, setAnchorEl] = React.useState<PopoverProps['anchorEl']>(null); const handleClose = () => { setOpen(false); }; const handleMouseUp = () => { const selection = window.getSelection(); // Ignore if the selection length is 0 if (!selection || selection.anchorOffset === selection.focusOffset) { return; } const getBoundingClientRect = () => { return selection.getRangeAt(0).getBoundingClientRect(); }; setOpen(true); setAnchorEl({ getBoundingClientRect, nodeType: 1 }); }; const id = open ? 'virtual-element-popover' : undefined; return ( <div> <Typography aria-describedby={id} onMouseUp={handleMouseUp}> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ipsum purus, bibendum sit amet vulputate eget, porta semper ligula. Donec bibendum vulputate erat, ac fringilla mi finibus nec. Donec ac dolor sed dolor porttitor blandit vel vel purus. Fusce vel malesuada ligula. Nam quis vehicula ante, eu finibus est. Proin ullamcorper fermentum orci, quis finibus massa. Nunc lobortis, massa ut rutrum ultrices, metus metus finibus ex, sit amet facilisis neque enim sed neque. Quisque accumsan metus vel maximus consequat. Suspendisse lacinia tellus a libero volutpat maximus. </Typography> <Popover id={id} open={open} anchorEl={anchorEl} anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }} onClose={handleClose} disableAutoFocus > <Paper> <Typography sx={{ p: 2 }}>The content of the Popover.</Typography> </Paper> </Popover> </div> ); }
For additional details on the properties of virtual elements, consult the following resources:
:::warning When using a virtual element with the Popover component, the
nodeType
property is required. This differs from virtual elements used in the Popper
or Tooltip
components, which do not mandate this property. :::Supplementary projects
For advanced scenarios, you may benefit from exploring:
material-ui-popup-state
The
material-ui-popup-state
package simplifies popover state management in most use cases.import * as React from 'react'; import Typography from '@mui/material/Typography'; import Button from '@mui/material/Button'; import Popover from '@mui/material/Popover'; import PopupState, { bindTrigger, bindPopover } from 'material-ui-popup-state'; export default function PopoverPopupState() { return ( <PopupState variant="popover" popupId="demo-popup-popover"> {(popupState) => ( <div> <Button variant="contained" {...bindTrigger(popupState)}> Open Popover </Button> <Popover {...bindPopover(popupState)} anchorOrigin={{ vertical: 'bottom', horizontal: 'center', }} transformOrigin={{ vertical: 'top', horizontal: 'center', }} > <Typography sx={{ p: 2 }}>The content of the Popover.</Typography> </Popover> </div> )} </PopupState> ); }