Skip to content

Commit

Permalink
Support the legacy API too
Browse files Browse the repository at this point in the history
  • Loading branch information
mnajdova committed Sep 12, 2023
1 parent 9e79f41 commit deceed9
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 45 deletions.
99 changes: 66 additions & 33 deletions docs/pages/experiments/material-next/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,43 +17,76 @@ const MenuButton = React.forwardRef(function MenuButton(
return <Button type="button" {...props} {...getButtonProps()} />;
});

export default function BasicMenu() {
// 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);
// };
function DropdownUsage() {
const { contextValue: dropdownContextValue } = useDropdown();

return (
<DropdownContext.Provider value={dropdownContextValue}>
<MenuButton
id="basic-button"
// aria-controls={open ? 'basic-menu' : undefined}
aria-haspopup="true"
// aria-expanded={open ? 'true' : undefined}
>
Dashboard
</MenuButton>
<Menu
id="basic-menu"
MenuListProps={{
'aria-labelledby': 'basic-button',
}}
>
<MenuItem /* onClick={handleClose} */>Profile</MenuItem>
<MenuItem /* onClick={handleClose} */>My account</MenuItem>
<MenuItem /* onClick={handleClose} */>Logout</MenuItem>
</Menu>
</DropdownContext.Provider>
);
}

function LegacyUsage() {
const [anchorEl, setAnchorEl] = React.useState(null);
const open = Boolean(anchorEl);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};

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

export default function BasicMenu() {
return (
<ThemeProvider theme={theme}>
<DropdownContext.Provider value={dropdownContextValue}>
<MenuButton
id="basic-button"
// aria-controls={open ? 'basic-menu' : undefined}
aria-haspopup="true"
// aria-expanded={open ? 'true' : undefined}
// onClick={handleClick}
>
Dashboard
</MenuButton>
<Menu
id="basic-menu"
// anchorEl={anchorEl}
// open={open}
// onClose={handleClose}
MenuListProps={{
'aria-labelledby': 'basic-button',
}}
>
<MenuItem /* onClick={handleClose} */>Profile</MenuItem>
<MenuItem /* onClick={handleClose} */>My account</MenuItem>
<MenuItem /* onClick={handleClose} */>Logout</MenuItem>
</Menu>
</DropdownContext.Provider>
<LegacyUsage />
<DropdownUsage />
</ThemeProvider>
);
}
54 changes: 42 additions & 12 deletions packages/mui-material-next/src/Menu/Menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useSlotProps } from '@mui/base/utils';
import { ListActionTypes } from '@mui/base/useList';
import { HTMLElementType } from '@mui/utils';
import Popover, { PopoverPaper } from '@mui/material/Popover';
import MenuList from '@mui/material/MenuList';
import { styled, useTheme, useThemeProps } from '@mui/material/styles';
import { rootShouldForwardProp } from '@mui/material/styles/styled';
import { getMenuUtilityClass } from './menuClasses';
Expand Down Expand Up @@ -55,7 +56,16 @@ export const MenuPaper = styled(PopoverPaper, {
WebkitOverflowScrolling: 'touch',
});

const MenuMenuList = styled('ul', {
const MenuMenuList = styled(MenuList, {
name: 'MuiMenu',
slot: 'List',
overridesResolver: (props, styles) => styles.list,
})({
// We disable the focus ring for mouse, touch and keyboard users.
outline: 0,
});

const MenuListbox = styled('ul', {
name: 'MuiMenu',
slot: 'List',
overridesResolver: (props, styles) => styles.list,
Expand All @@ -68,14 +78,14 @@ const Menu = React.forwardRef(function Menu(inProps, ref) {
const props = useThemeProps({ props: inProps, name: 'MuiMenu' });

const {
anchorEl,
autoFocus = true,
children,
className,
disableAutoFocusItem = false,
MenuListProps = {},
onClose,
// no prop, only context value
// open,
open: openProp,
PaperProps = {},
PopoverClasses,
transitionDuration = 'auto',
Expand All @@ -102,10 +112,21 @@ const Menu = React.forwardRef(function Menu(inProps, ref) {
variant,
};

const { contextValue, getListboxProps, dispatch, open, triggerElement } = useMenu({
const {
contextValue,
getListboxProps,
dispatch,
open: contextOpen,
triggerElement,
} = useMenu({
// onItemsChange,
});

const open = openProp ?? contextOpen;

// contextValue !== undefined can be the other condition, but there could be scenario where the Dropdown can be an ancestor somewhere in the React tree
const usingContext = openProp === undefined;

React.useImperativeHandle(
actions,
() => ({
Expand Down Expand Up @@ -197,13 +218,19 @@ const Menu = React.forwardRef(function Menu(inProps, ref) {
className: classes.paper,
});

const Listbox = slots.listbox ?? MenuMenuList;
const Listbox = slots.listbox ?? usingContext ? MenuListbox : MenuMenuList;
const listboxProps = useSlotProps({
elementType: Listbox,
// add handleListKeydown
getSlotProps: getListboxProps,
// slotProps.listbox can also be a callback, fix this
externalSlotProps: { ...slotProps.listbox, ...MenuListProps },
getSlotProps: (otherHandlers) => {
return getListboxProps({
onKeyDown: handleListKeyDown,
...otherHandlers,
});
},
externalSlotProps: (args) => ({
...(typeof slotProps.listbox === 'function' ? slotProps.listbox(args) : slotProps.listbox),
...MenuListProps,
}),
additionalProps: {
variant,
autoFocusItem,
Expand Down Expand Up @@ -234,12 +261,15 @@ const Menu = React.forwardRef(function Menu(inProps, ref) {
transitionDuration={transitionDuration}
TransitionProps={{ onEntering: handleEntering, ...TransitionProps }}
ownerState={ownerState}
anchorEl={anchorEl ?? triggerElement}
{...other}
classes={PopoverClasses}
>
<MenuMenuList {...listboxProps} {...MenuListProps}>
<MenuProvider value={contextValue}>{children}</MenuProvider>
</MenuMenuList>
<MenuProvider value={contextValue}>
<MenuMenuList {...listboxProps} {...MenuListProps}>
{children}
</MenuMenuList>
</MenuProvider>
</MenuRoot>
);
});
Expand Down

0 comments on commit deceed9

Please sign in to comment.