JGuang

Menu

Menu · Material UI

Preview
npm install @mui/material@9.4.0 @emotion/react@11.14.0 @emotion/styled@11.14.1

Menu

Offer transient actions with native menu keyboard navigation and selection.

This guide covers Material UI Core with the default Emotion engine; extensions and additional demos are explicitly classified.

Use case and business boundary

MenuItem activation is not routing or saving; anchor, open state and closing policy must be supplied.

Native composition and scope

Menu, MenuItem, MenuList, ClickAwayListener, Popover, Popper

Preserve native Material UI composition and types; do not substitute JGuang UI/Base UI/Radix APIs. Example entries are not extra components.

Native installation and initialization

npm install @mui/material@9.4.0 @emotion/react@11.14.0 @emotion/styled@11.14.1

Use native npm and Emotion, not an invented JGuang UI Registry URL. Place examples inside native ThemeProvider; choose CssBaseline or ScopedCssBaseline for the project. Inspect React, existing providers, lockfile and SSR first. Never overwrite files or conceal peer conflicts. This batch verified React 19.2.8; React 18 and below require matching react-is. See the included bilingual setup guide.

Practical native parameters

These selected parameters are not a flattened universal API. Preserve the native declaring owner, slot structure, nullable values and generics.

Owner.propPractical roleDeclaration source
Menu.openControlled native visibility; it does not fetch data or execute actions.Menu
Menu.anchorElActual or supported virtual anchor; preserve the owning type and lifetime.Menu
Menu.onCloseNative request to close; reason/event signatures differ and the host updates open.Menu
MenuItem.selectedNative selected/pressed presentation; the host owns the selected value.MenuItem
MenuItem.disabledNative disabled interaction state; not an authorization check.ButtonBase

Runnable native examples

Machine keys select example entries, not universal variant props. Native demo JSX/data stay unchanged; JGuang-authored acceptance fixtures are explicitly labelled.

  • Basic menu · BasicMenu · upstream native demo
  • Icon menu · IconMenu · upstream native demo
  • Dense menu · DenseMenu · upstream native demo
  • Selected menu · SimpleListMenu · upstream native demo
  • Checkbox and radio menu items · CheckboxMenu · upstream native demo
  • Checkbox and radio menu items · RadioMenu · upstream native demo
  • Positioned menu · PositionedMenu · upstream native demo
  • Composition with Menu List · MenuListComposition · upstream native demo
  • Account menu · AccountMenu · upstream native demo
  • Customization · CustomizedMenus · upstream native demo
  • Max height menu · LongMenu · upstream native demo
  • Limitations · TypographyMenu · upstream native demo
  • Change transition · FadeMenu · upstream native demo
  • Context menu · ContextMenu · upstream native demo
  • Grouped Menu · GroupedMenu · upstream native demo

Explicitly unsupported additional examples

These remain in the upstream inventory, not silently skipped or presented as working previews. Additional dependency/framework acceptance is required.

  • material-ui-popup-state · MenuPopupState: material-ui-popup-state

Actual usage example

Unmodified pinned native demo; copy its required local helper files together.

import * as React from 'react';
import Button from '@mui/material/Button';
import Menu from '@mui/material/Menu';
import MenuItem from '@mui/material/MenuItem';

export default function BasicMenu() {
  const id = React.useId();
  const buttonId = `${id}-button`;
  const menuId = `${id}-menu`;
  const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
  const open = Boolean(anchorEl);
  const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
    setAnchorEl(event.currentTarget);
  };
  const handleClose = () => {
    setAnchorEl(null);
  };

  return (
    <div>
      <Button
        id={buttonId}
        aria-controls={open ? menuId : undefined}
        aria-haspopup="true"
        aria-expanded={open}
        onClick={handleClick}
      >
        Dashboard
      </Button>
      <Menu
        id={menuId}
        anchorEl={anchorEl}
        open={open}
        onClose={handleClose}
        slotProps={{
          list: {
            'aria-labelledby': buttonId,
          },
        }}
      >
        <MenuItem onClick={handleClose}>Profile</MenuItem>
        <MenuItem onClick={handleClose}>My account</MenuItem>
        <MenuItem onClick={handleClose}>Logout</MenuItem>
      </Menu>
    </div>
  );
}

Example dependency boundaries

react, @mui/material/Button, @mui/material/Menu, @mui/material/MenuItem, @mui/material/Divider, @mui/material/Paper, @mui/material/MenuList, @mui/material/ListItemText, @mui/material/ListItemIcon, @mui/material/Typography, @mui/icons-material/ContentCut, @mui/icons-material/ContentCopy, @mui/icons-material/ContentPaste, @mui/icons-material/Cloud, @mui/icons-material/Check, @mui/material/List, @mui/material/ListItemButton, @mui/icons-material/RadioButtonChecked, @mui/icons-material/RadioButtonUnchecked, @mui/material/ClickAwayListener, @mui/material/Grow, @mui/material/Popper, @mui/material/Stack, @mui/material/Box, @mui/material/Avatar, @mui/material/IconButton, @mui/material/Tooltip, @mui/icons-material/PersonAdd, @mui/icons-material/Settings, @mui/icons-material/Logout, @mui/material/styles, @mui/icons-material/Edit, @mui/icons-material/Archive, @mui/icons-material/FileCopy, @mui/icons-material/MoreHoriz, @mui/icons-material/KeyboardArrowDown, @mui/icons-material/MoreVert, @mui/icons-material/Drafts, @mui/icons-material/Send, @mui/icons-material/PriorityHigh, @mui/material/Fade, @mui/material/ListSubheader

Direct Icons/System/Utils example imports require their matching 9.4.0 packages. Relative data/helpers are part of the example closure, not extra components. Remote images and simulated operations do not supply a backend.

Pinned upstream API metadata reference

These tables retain the upstream metadata, not a newly inferred generic type system. Conditional generics, inherited props and callback details are defined by the source declarations below. Theme defaults may override metadata defaults.

import Menu from '@mui/material/Menu';
import { Menu } from '@mui/material';

Native inheritance: Popover. Parent/DOM props are not fabricated as additional own props.

PropRequiredUpstream metadata type / constraintMetadata default
openyesbool—
anchorElnoHTML element | func—
autoFocusnobooltrue
childrennonode—
classesnoobject—
disableAutoFocusItemnoboolfalse
onClosenofunc—
PopoverClassesnoobject—
slotPropsno{ backdrop?: func | object, list?: func | object, paper?: func | object, root?: func | object, transition?: func | object }{}
slotsno{ backdrop?: elementType, list?: elementType, paper?: elementType, root?: elementType, transition?: elementType }{}
sxnoArray<func | object | bool> | func | object—
transitionDurationno'auto' | number | { appear?: number, enter?: number, exit?: number }'auto'
variantno'menu' | 'selectedMenu''selectedMenu'
import MenuItem from '@mui/material/MenuItem';
import { MenuItem } from '@mui/material';

Native inheritance: ButtonBase. Parent/DOM props are not fabricated as additional own props.

PropRequiredUpstream metadata type / constraintMetadata default
autoFocusnoboolfalse
childrennonode—
classesnoobject—
componentnoelementType—
densenoboolfalse
disableGuttersnoboolfalse
dividernoboolfalse
focusVisibleClassNamenostring—
selectednoboolfalse
sxnoArray<func | object | bool> | func | object—
import MenuList from '@mui/material/MenuList';
import { MenuList } from '@mui/material';

Native inheritance: List. Parent/DOM props are not fabricated as additional own props.

PropRequiredUpstream metadata type / constraintMetadata default
autoFocusnoboolfalse
autoFocusItemnoboolfalse
childrennonode—
disabledItemsFocusablenoboolfalse
disableListWrapnoboolfalse
variantno'menu' | 'selectedMenu''selectedMenu'

ClickAwayListener

import ClickAwayListener from '@mui/material/ClickAwayListener';
import { ClickAwayListener } from '@mui/material';
PropRequiredUpstream metadata type / constraintMetadata default
childrenyeselement—
onClickAwayyesfunc—
disableReactTreenoboolfalse
mouseEventno'onClick' | 'onMouseDown' | 'onMouseUp' | 'onPointerDown' | 'onPointerUp' | false'onClick'
touchEventno'onTouchEnd' | 'onTouchStart' | false'onTouchEnd'

Popover

import Popover from '@mui/material/Popover';
import { Popover } from '@mui/material';

Native inheritance: Modal. Parent/DOM props are not fabricated as additional own props.

PropRequiredUpstream metadata type / constraintMetadata default
openyesbool—
actionnoref—
anchorElnoHTML element | func—
anchorOriginno{ horizontal: 'center' | 'left' | 'right' | number, vertical: 'bottom' | 'center' | 'top' | number }{ vertical: 'top', horizontal: 'left', }
anchorPositionno{ left: number, top: number }—
anchorReferenceno'anchorEl' | 'anchorPosition' | 'none''anchorEl'
childrennonode—
classesnoobject—
containernoHTML element | func—
disableAutoFocusnoboolfalse
disableScrollLocknoboolfalse
elevationnointeger8
marginThresholdnonumber16
onClosenofunc—
slotPropsno{ backdrop?: func | object, paper?: func | object, root?: func | object, transition?: func | object }{}
slotsno{ backdrop?: elementType, paper?: elementType, root?: elementType, transition?: elementType }{}
sxnoArray<func | object | bool> | func | object—
transformOriginno{ horizontal: 'center' | 'left' | 'right' | number, vertical: 'bottom' | 'center' | 'top' | number }{ vertical: 'top', horizontal: 'left', }
transitionDurationno'auto' | number | { appear?: number, enter?: number, exit?: number }'auto'

Popper

import Popper from '@mui/material/Popper';
import { Popper } from '@mui/material';
PropRequiredUpstream metadata type / constraintMetadata default
openyesbool—
anchorElnoHTML element | object | func—
childrennonode | func—
componentnoelementType—
containernoHTML element | func—
disablePortalnoboolfalse
keepMountednoboolfalse
modifiersnoArray<{ data?: object, effect?: func, enabled?: bool, fn?: func, name?: any, options?: object, phase?: 'afterMain' | 'afterRead' | 'afterWrite' | 'beforeMain' | 'beforeRead' | 'beforeWrite' | 'main' | 'read' | 'write', requires?: Array<string>, requiresIfExists?: Array<string> }>—
placementno'auto-end' | 'auto-start' | 'auto' | 'bottom-end' | 'bottom-start' | 'bottom' | 'left-end' | 'left-start' | 'left' | 'right-end' | 'right-start' | 'right' | 'top-end' | 'top-start' | 'top''bottom'
popperOptionsno{ modifiers?: array, onFirstUpdate?: func, placement?: 'auto-end' | 'auto-start' | 'auto' | 'bottom-end' | 'bottom-start' | 'bottom' | 'left-end' | 'left-start' | 'left' | 'right-end' | 'right-start' | 'right' | 'top-end' | 'top-start' | 'top', strategy?: 'absolute' | 'fixed' }{}
popperRefnoref—
slotPropsno{ root?: func | object }{}
slotsno{ root?: elementType }{}
sxnoArray<func | object | bool> | func | object—
transitionnoboolfalse

Native source declarations

Declarations/imports are extracted from pinned source without flattening unions or external inheritance. Original English comments/types are source reference, not a claim of translated upstream prose. Shared types stay in their native packages.

vendor/src/Menu/Menu.d.ts

import * as React from 'react';

import { SxProps } from '@mui/system';

import { Theme } from '../styles';

import { InternalStandardProps as StandardProps } from '../internal';

import { PaperProps } from '../Paper';

import { PopoverProps } from '../Popover';

import { MenuListProps } from '../MenuList';

import { ModalProps } from '../Modal';

import { BackdropProps } from '../Backdrop';

import { TransitionProps } from '../transitions/types';

import { MenuClasses } from './menuClasses';

import { CreateSlotsAndSlotProps, SlotComponentProps, SlotProps } from '../utils/types';

export interface MenuRootSlotPropsOverrides {}

export interface MenuPaperSlotPropsOverrides {}

export interface MenuTransitionSlotPropsOverrides {}

export interface MenuListSlotPropsOverrides {}

export interface MenuBackdropSlotPropsOverrides {}

export interface MenuSlots {
  /**
   * The component used for the popper.
   * @default Modal
   */
  root: React.ElementType;
  /**
   * The component used for the paper.
   * @default PopoverPaper
   */
  paper: React.ElementType;
  /**
   * The component used for the list.
   * @default MenuList
   */
  list: React.ElementType;
  /**
   * The component used for the transition slot.
   * @default Grow
   */
  transition: React.ElementType;
  /**
   * The component used for the backdrop slot.
   * @default Backdrop
   */
  backdrop: React.ElementType;
}

export type MenuSlotsAndSlotProps = CreateSlotsAndSlotProps<
  MenuSlots,
  {
    /**
     * Props forwarded to the root slot.
     * By default, the available props are based on the [Popover](https://mui.com/material-ui/api/popover/#props) component.
     */
    root: SlotProps<React.ElementType<ModalProps>, MenuRootSlotPropsOverrides, MenuOwnerState>;
    /**
     * Props forwarded to the paper slot.
     * By default, the available props are based on the [Paper](https://mui.com/material-ui/api/paper/#props) component.
     */
    paper: SlotProps<React.ElementType<PaperProps>, MenuPaperSlotPropsOverrides, MenuOwnerState>;
    /**
     * Props forwarded to the list slot.
     * By default, the available props are based on the [MenuList](https://mui.com/material-ui/api/menu-list/#props) component.
     */
    list: SlotProps<React.ElementType<MenuListProps>, MenuListSlotPropsOverrides, MenuOwnerState>;
    /**
     * Props forwarded to the transition slot.
     * By default, the available props are based on the [Grow](https://mui.com/material-ui/api/grow/#props) component.
     */
    transition: SlotComponentProps<
      // use SlotComponentProps because transition slot does not support `component` and `sx` prop
      React.ElementType<TransitionProps>,
      TransitionProps & MenuTransitionSlotPropsOverrides,
      MenuOwnerState
    >;
    /**
     * Props forwarded to the backdrop slot.
     * By default, the available props are based on the [Backdrop](https://mui.com/material-ui/api/backdrop/#props) component.
     */
    backdrop: SlotProps<
      React.ElementType<BackdropProps>,
      MenuBackdropSlotPropsOverrides,
      MenuOwnerState
    >;
  }
>;

export interface MenuProps
  extends StandardProps<Omit<PopoverProps, 'slots' | 'slotProps'>>, MenuSlotsAndSlotProps {
  /**
   * An HTML element, or a function that returns one.
   * It's used to set the position of the menu.
   */
  anchorEl?: PopoverProps['anchorEl'] | undefined;
  /**
   * If `true` (Default) will focus the `[role="menu"]` if no focusable child is found. Disabled
   * children are not focusable. If you set this prop to `false` focus will be placed
   * on the parent modal container. This has severe accessibility implications
   * and should only be considered if you manage focus otherwise.
   * @default true
   */
  autoFocus?: boolean | undefined;
  /**
   * Menu contents, normally `MenuItem`s.
   */
  children?: React.ReactNode;
  /**
   * Override or extend the styles applied to the component.
   */
  classes?: Partial<MenuClasses> | undefined;
  /**
   * When opening the menu will not focus the active item but the `[role="menu"]`
   * unless `autoFocus` is also set to `false`. Not using the default means not
   * following WAI-ARIA authoring practices. Please be considerate about possible
   * accessibility implications.
   * @default false
   */
  disableAutoFocusItem?: boolean | undefined;
  /**
   * Callback fired when the component requests to be closed.
   *
   * @param {object} event The event source of the callback.
   * @param {string} reason Can be: `"escapeKeyDown"`, `"backdropClick"`, `"tabKeyDown"`.
   */
  onClose?: PopoverProps['onClose'] | undefined;
  /**
   * If `true`, the component is shown.
   */
  open: boolean;
  /**
   * `classes` prop applied to the [`Popover`](https://mui.com/material-ui/api/popover/) element.
   */
  PopoverClasses?: PopoverProps['classes'] | undefined;
  /**
   * The system prop that allows defining system overrides as well as additional CSS styles.
   */
  sx?: SxProps<Theme> | undefined;
  /**
   * The length of the transition in `ms`, or 'auto'
   * @default 'auto'
   */
  transitionDuration?: TransitionProps['timeout'] | 'auto' | undefined;
  /**
   * The variant to use. Use `menu` to prevent selected items from impacting the initial focus.
   * @default 'selectedMenu'
   */
  variant?: 'menu' | 'selectedMenu' | undefined;
}

export interface MenuOwnerState extends Omit<MenuProps, 'slots' | 'slotProps'> {}

export declare const MenuPaper: React.FC<PaperProps>;

export default function Menu(props: MenuProps): React.JSX.Element;

vendor/src/MenuItem/MenuItem.d.ts

import * as React from 'react';

import { SxProps } from '@mui/system';

import { Theme } from '../styles';

import { ExtendButtonBase, ExtendButtonBaseTypeMap } from '../ButtonBase';

import { OverrideProps } from '../OverridableComponent';

import { MenuItemClasses } from './menuItemClasses';

export interface MenuItemOwnProps {
  /**
   * If `true`, the list item is focused during the first mount.
   * Focus will also be triggered if the value changes from false to true.
   * @default false
   */
  autoFocus?: boolean | undefined;
  /**
   * Override or extend the styles applied to the component.
   */
  classes?: Partial<MenuItemClasses> | undefined;
  /**
   * If `true`, compact vertical padding designed for keyboard and mouse input is used.
   * The prop defaults to the value inherited from the parent Menu component.
   * @default false
   */
  dense?: boolean | undefined;
  /**
   * If `true`, the component is disabled.
   * @default false
   */
  disabled?: boolean | undefined;
  /**
   * If `true`, the left and right padding is removed.
   * @default false
   */
  disableGutters?: boolean | undefined;
  /**
   * If `true`, a 1px light border is added to the bottom of the menu item.
   * @default false
   */
  divider?: boolean | undefined;
  /**
   * If `true`, the component is selected.
   * For `menuitemcheckbox` and `menuitemradio` roles, this also drives `aria-checked`.
   * @default false
   */
  selected?: boolean | undefined;
  /**
   * The system prop that allows defining system overrides as well as additional CSS styles.
   */
  sx?: SxProps<Theme> | undefined;
}

export type MenuItemTypeMap<
  AdditionalProps = {},
  RootComponent extends React.ElementType = 'li',
> = ExtendButtonBaseTypeMap<{
  props: AdditionalProps & MenuItemOwnProps;
  defaultComponent: RootComponent;
}>;

declare const MenuItem: ExtendButtonBase<MenuItemTypeMap>;

export type MenuItemProps<
  RootComponent extends React.ElementType = MenuItemTypeMap['defaultComponent'],
  AdditionalProps = {},
> = OverrideProps<MenuItemTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
  component?: React.ElementType | undefined;
};

vendor/src/MenuList/MenuList.d.ts

import * as React from 'react';

import { ExtendList, ExtendListTypeMap } from '../List';

import { OverrideProps } from '../OverridableComponent';

export interface MenuListOwnProps {
  /**
   * If `true`, will focus the `[role="menu"]` container and move into tab order.
   * @default false
   */
  autoFocus?: boolean | undefined;
  /**
   * If `true`, will focus the first menuitem if `variant="menu"` or selected item
   * if `variant="selectedMenu"`.
   * @default false
   */
  autoFocusItem?: boolean | undefined;
  /**
   * MenuList contents, normally `MenuItem`s.
   */
  children?: React.ReactNode;
  /**
   * If `true`, will allow focus on disabled items.
   * @default false
   */
  disabledItemsFocusable?: boolean | undefined;
  /**
   * If `true`, the menu items will not wrap focus.
   * @default false
   */
  disableListWrap?: boolean | undefined;
  /**
   * The variant to use. Use `menu` to prevent selected items from impacting the initial focus
   * and the vertical alignment relative to the anchor element.
   * @default 'selectedMenu'
   */
  variant?: 'menu' | 'selectedMenu' | undefined;
}

export type MenuListTypeMap<
  AdditionalProps = {},
  RootComponent extends React.ElementType = 'ul',
> = ExtendListTypeMap<{
  props: AdditionalProps & MenuListOwnProps;
  defaultComponent: RootComponent;
}>;

export type MenuListClassKey = keyof NonNullable<MenuListTypeMap['props']['classes']>;

declare const MenuList: ExtendList<MenuListTypeMap>;

export type MenuListProps<
  RootComponent extends React.ElementType = MenuListTypeMap['defaultComponent'],
  AdditionalProps = {},
> = OverrideProps<MenuListTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
  component?: React.ElementType | undefined;
};

vendor/src/ClickAwayListener/ClickAwayListener.tsx

import * as React from 'react';

import PropTypes from 'prop-types';

import contains from '@mui/utils/contains';

import ownerDocument from '@mui/utils/ownerDocument';

import useForkRef from '@mui/utils/useForkRef';

import useEventCallback from '@mui/utils/useEventCallback';

import elementAcceptingRef from '@mui/utils/elementAcceptingRef';

import exactProp from '@mui/utils/exactProp';

import getReactElementRef from '@mui/utils/getReactElementRef';

type ClickAwayMouseEventHandler =
  'onClick' | 'onMouseDown' | 'onMouseUp' | 'onPointerDown' | 'onPointerUp';

type ClickAwayTouchEventHandler = 'onTouchStart' | 'onTouchEnd';

export interface ClickAwayListenerProps {
  /**
   * The wrapped element.
   */
  children: React.ReactElement<any>;
  /**
   * If `true`, the React tree is ignored and only the DOM tree is considered.
   * This prop changes how portaled elements are handled.
   * @default false
   */
  disableReactTree?: boolean | undefined;
  /**
   * The mouse event to listen to. You can disable the listener by providing `false`.
   * @default 'onClick'
   */
  mouseEvent?: ClickAwayMouseEventHandler | false | undefined;
  /**
   * Callback fired when a "click away" event is detected.
   */
  onClickAway: (event: MouseEvent | TouchEvent) => void;
  /**
   * The touch event to listen to. You can disable the listener by providing `false`.
   * @default 'onTouchEnd'
   */
  touchEvent?: ClickAwayTouchEventHandler | false | undefined;
}

vendor/src/Popover/Popover.d.ts

import * as React from 'react';

import { SxProps } from '@mui/system';

import { SlotComponentProps } from '@mui/utils/types';

import { BackdropProps } from '../Backdrop';

import { Theme } from '../styles';

import { InternalStandardProps as StandardProps } from '../internal';

import { PaperProps } from '../Paper';

import { ModalProps } from '../Modal';

import { TransitionProps } from '../transitions/types';

import { PopoverClasses } from './popoverClasses';

import { CreateSlotsAndSlotProps, SlotProps } from '../utils/types';

export interface PopoverSlots {
  /**
   * The component used for the root slot.
   * @default Modal
   */
  root: React.ElementType;
  /**
   * The component used for the paper slot.
   * @default Paper
   */
  paper: React.ElementType;
  /**
   * The component used for the transition slot.
   * @default Grow
   */
  transition: React.ElementType;
  /**
   * The component used for the backdrop slot.
   * @default Backdrop
   */
  backdrop: React.ElementType;
}

export interface PopoverRootSlotPropsOverrides {}

export interface PopoverPaperSlotPropsOverrides {}

export interface PopoverTransitionSlotPropsOverrides {}

export interface PopoverBackdropSlotPropsOverrides {}

export type PopoverSlotsAndSlotProps = CreateSlotsAndSlotProps<
  PopoverSlots,
  {
    /**
     * Props forwarded to the root slot.
     * By default, the available props are based on the [Modal](https://mui.com/material-ui/api/modal/#props) component.
     */
    root: SlotProps<
      React.ElementType<ModalProps>,
      PopoverRootSlotPropsOverrides,
      PopoverOwnerState
    >;
    /**
     * Props forwarded to the paper slot.
     * By default, the available props are based on the [Paper](https://mui.com/material-ui/api/paper/#props) component.
     */
    paper: SlotProps<
      React.ElementType<PaperProps>,
      PopoverPaperSlotPropsOverrides,
      PopoverOwnerState
    >;
    /**
     * Props forwarded to the transition slot.
     * By default, the available props are based on the [Grow](https://mui.com/material-ui/api/grow/#props) component.
     */
    transition: SlotComponentProps<
      // use SlotComponentProps because transition slot does not support `component` and `sx` prop
      React.ElementType<TransitionProps>,
      TransitionProps & PopoverTransitionSlotPropsOverrides,
      PopoverOwnerState
    >;
    /**
     * Props forwarded to the backdrop slot.
     * By default, the available props are based on the [Backdrop](https://mui.com/material-ui/api/backdrop/#props) component.
     */
    backdrop: SlotProps<
      React.ElementType<BackdropProps>,
      PopoverBackdropSlotPropsOverrides,
      PopoverOwnerState
    >;
  }
>;

export interface PopoverOrigin {
  vertical: 'top' | 'center' | 'bottom' | number;
  horizontal: 'left' | 'center' | 'right' | number;
}

export interface PopoverPosition {
  top: number;
  left: number;
}

export type PopoverReference = 'anchorEl' | 'anchorPosition' | 'none';

interface PopoverVirtualElement {
  getBoundingClientRect: () => DOMRect;
  nodeType: Node['ELEMENT_NODE'];
}

export interface PopoverProps
  extends
    StandardProps<
      Omit<ModalProps, 'slots' | 'slotProps' | 'BackdropProps' | 'BackdropComponent'>,
      'children'
    >,
    PopoverSlotsAndSlotProps {
  /**
   * A ref for imperative actions.
   * It currently only supports updatePosition() action.
   */
  action?: React.Ref<PopoverActions> | undefined;
  /**
   * An HTML element, [PopoverVirtualElement](https://mui.com/material-ui/react-popover/#virtual-element),
   * or a function that returns either.
   * It's used to set the position of the popover.
   */
  anchorEl?:
    | null
    | Element
    | PopoverVirtualElement
    | (() => Element | PopoverVirtualElement | null)
    | undefined;
  /**
   * This is the point on the anchor where the popover's
   * `anchorEl` will attach to. This is not used when the
   * anchorReference is 'anchorPosition'.
   *
   * Options:
   * vertical: [top, center, bottom];
   * horizontal: [left, center, right].
   * @default {
   *   vertical: 'top',
   *   horizontal: 'left',
   * }
   */
  anchorOrigin?: PopoverOrigin | undefined;
  /**
   * This is the position that may be used to set the position of the popover.
   * The coordinates are relative to the application's client area.
   */
  anchorPosition?: PopoverPosition | undefined;
  /**
   * This determines which anchor prop to refer to when setting
   * the position of the popover.
   * @default 'anchorEl'
   */
  anchorReference?: PopoverReference | undefined;
  /**
   * The content of the component.
   */
  children?: React.ReactNode;
  /**
   * Override or extend the styles applied to the component.
   */
  classes?: Partial<PopoverClasses> | undefined;
  /**
   * An HTML element, component instance, or function that returns either.
   * The `container` will passed to the Modal component.
   *
   * By default, it uses the body of the anchorEl's top-level document object,
   * so it's simply `document.body` most of the time.
   */
  container?: ModalProps['container'] | undefined;
  /**
   * The elevation of the popover.
   * @default 8
   */
  elevation?: number | undefined;
  /**
   * Specifies how close to the edge of the window the popover can appear.
   * If null, the popover will not be constrained by the window.
   * @default 16
   */
  marginThreshold?: number | null | undefined;
  onClose?: ModalProps['onClose'] | undefined;
  /**
   * If `true`, the component is shown.
   */
  open: boolean;
  /**
   * The system prop that allows defining system overrides as well as additional CSS styles.
   */
  sx?: SxProps<Theme> | undefined;
  /**
   * This is the point on the popover which
   * will attach to the anchor's origin.
   *
   * Options:
   * vertical: [top, center, bottom, x(px)];
   * horizontal: [left, center, right, x(px)].
   * @default {
   *   vertical: 'top',
   *   horizontal: 'left',
   * }
   */
  transformOrigin?: PopoverOrigin | undefined;
  /**
   * Set to 'auto' to automatically calculate transition time based on height.
   * @default 'auto'
   */
  transitionDuration?: TransitionProps['timeout'] | 'auto' | undefined;
}

export interface PopoverOwnerState extends Omit<PopoverProps, 'slots' | 'slotProps'> {}

export interface PopoverActions {
  updatePosition(): void;
}

export function getOffsetTop(rect: DOMRect, vertical: number | 'center' | 'bottom' | 'top'): number;

export function getOffsetLeft(
  rect: DOMRect,
  horizontal: number | 'center' | 'right' | 'left',
): number;

type PopoverRootProps = NonNullable<PopoverProps['slotProps']>['root'];

type PopoverPaperProps = NonNullable<PopoverProps['slotProps']>['paper'];

export declare const PopoverRoot: React.FC<PopoverRootProps>;

export declare const PopoverPaper: React.FC<PopoverPaperProps>;

export default function Popover(props: PopoverProps): React.JSX.Element;

vendor/src/Popper/Popper.tsx

import { SxProps } from '@mui/system';

import { useRtl } from '@mui/system/RtlProvider';

import refType from '@mui/utils/refType';

import HTMLElementType from '@mui/utils/HTMLElementType';

import PropTypes from 'prop-types';

import * as React from 'react';

import BasePopper from './BasePopper';

import { PopperProps as BasePopperProps } from './BasePopper.types';

import { Theme } from '../styles';

import { styled } from '../zero-styled';

import { useDefaultProps } from '../DefaultPropsProvider';

export interface PopperProps extends Omit<BasePopperProps, 'direction'> {
  /**
   * The component used for the root node.
   * Either a string to use a HTML element or a component.
   */
  component?: React.ElementType | undefined;
  /**
   * The system prop that allows defining system overrides as well as additional CSS styles.
   */
  sx?: SxProps<Theme> | undefined;
}

Post-install acceptance

Run strict types, production build and real interactions. Check keyboard labels/focus, disabled/error/read-only semantics where natively supported, both themes, narrow screens and reduced motion. Verify callbacks against the real host data; do not declare installation complete from copying a prompt. Initialization fixtures also require server HTML and warning-free hydration.

Source and license

https://github.com/mui/material-ui/tree/809a7717b4c050ba3f69b75300689f07c050a16e

MIT · @mui/material@9.4.0. Vendor originals and license are preserved. Full original upstream prose remains in vendor/docs and is not represented as fully translated.