From ed87699d141fe1572aa4158b9c6e587290190ce9 Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Thu, 2 Jan 2025 14:31:39 +0700 Subject: [PATCH 01/10] complete slotProps on Menu --- packages/mui-material/src/Menu/Menu.d.ts | 42 +++++++++++++++++++- packages/mui-material/src/Menu/Menu.js | 21 +++++++--- packages/mui-material/src/Menu/Menu.spec.tsx | 24 +++++++++++ packages/mui-material/src/Menu/Menu.test.js | 42 ++++++++++++++++++-- 4 files changed, 118 insertions(+), 11 deletions(-) create mode 100644 packages/mui-material/src/Menu/Menu.spec.tsx diff --git a/packages/mui-material/src/Menu/Menu.d.ts b/packages/mui-material/src/Menu/Menu.d.ts index 9170b8ba9aaa7a..d87ce36f06f2df 100644 --- a/packages/mui-material/src/Menu/Menu.d.ts +++ b/packages/mui-material/src/Menu/Menu.d.ts @@ -4,11 +4,47 @@ import { InternalStandardProps as StandardProps } from '..'; import { PaperProps } from '../Paper'; import { PopoverProps } from '../Popover'; import { MenuListProps } from '../MenuList'; +import { ModalOwnProps } from '../Modal'; import { Theme } from '../styles'; import { TransitionProps } from '../transitions/transition'; import { MenuClasses } from './menuClasses'; +import { CreateSlotsAndSlotProps, SlotProps } from '../utils/types'; -export interface MenuProps extends StandardProps { +export interface MenuRootSlotPropsOverrides {} + +export interface MenuPaperSlotPropsOverrides {} + +export interface MenuTransitionSlotPropsOverrides {} + +export interface MenuListSlotPropsOverrides {} + +export interface MenuSlots { + /** + * The content of the component. + */ + root: React.ElementType; + paper: React.ElementType; + transition: React.ElementType; + list: React.ElementType; +} + +export type MenuSlotsAndSlotProps = CreateSlotsAndSlotProps< + MenuSlots, + { + root: SlotProps, MenuRootSlotPropsOverrides, MenuOwnerState>; + paper: SlotProps, MenuPaperSlotPropsOverrides, MenuOwnerState>; + transition: SlotProps< + React.ElementType, + MenuTransitionSlotPropsOverrides, + MenuOwnerState + >; + list: SlotProps, MenuListSlotPropsOverrides, MenuOwnerState>; + } +>; + +export interface MenuProps + extends StandardProps>, + MenuSlotsAndSlotProps { /** * An HTML element, or a function that returns one. * It's used to set the position of the menu. @@ -40,6 +76,7 @@ export interface MenuProps extends StandardProps { disableAutoFocusItem?: boolean; /** * Props applied to the [`MenuList`](https://mui.com/material-ui/api/menu-list/) element. + * @deprecated use the `slotProps.list` prop instead. This prop will be removed in v7. See [Migrating from deprecated APIs](https://mui.com/material-ui/migration/migrating-from-deprecated-apis/) for more details. * @default {} */ MenuListProps?: Partial; @@ -70,6 +107,7 @@ export interface MenuProps extends StandardProps { /** * Props applied to the transition element. * By default, the element is based on this [`Transition`](https://reactcommunity.org/react-transition-group/transition/) component. + * @deprecated use the `slotProps.transition` prop instead. This prop will be removed in v7. See [Migrating from deprecated APIs](https://mui.com/material-ui/migration/migrating-from-deprecated-apis/) for more details. * @default {} */ TransitionProps?: TransitionProps; @@ -80,6 +118,8 @@ export interface MenuProps extends StandardProps { variant?: 'menu' | 'selectedMenu'; } +export interface MenuOwnerState extends MenuProps {} + export declare const MenuPaper: React.FC; /** diff --git a/packages/mui-material/src/Menu/Menu.js b/packages/mui-material/src/Menu/Menu.js index 15342819d76647..f000722542a1c8 100644 --- a/packages/mui-material/src/Menu/Menu.js +++ b/packages/mui-material/src/Menu/Menu.js @@ -13,6 +13,7 @@ import rootShouldForwardProp from '../styles/rootShouldForwardProp'; import { styled } from '../zero-styled'; import { useDefaultProps } from '../DefaultPropsProvider'; import { getMenuUtilityClass } from './menuClasses'; +import useSlot from '../utils/useSlot'; const RTL_ORIGIN = { vertical: 'top', @@ -79,7 +80,7 @@ const Menu = React.forwardRef(function Menu(inProps, ref) { PaperProps = {}, PopoverClasses, transitionDuration = 'auto', - TransitionProps: { onEntering, ...TransitionProps } = {}, + TransitionProps = {}, variant = 'selectedMenu', slots = {}, slotProps = {}, @@ -88,6 +89,8 @@ const Menu = React.forwardRef(function Menu(inProps, ref) { const isRtl = useRtl(); + const { onEntering, ...transitionProps } = slotProps.transition ?? TransitionProps; + const ownerState = { ...props, autoFocus, @@ -179,6 +182,13 @@ const Menu = React.forwardRef(function Menu(inProps, ref) { className: classes.paper, }); + const [ListSlot, listSlotProps] = useSlot('list', { + elementType: MenuMenuList, + externalForwardedProps: { slots, slotProps }, + ownerState, + className: clsx(classes.list, MenuListProps.className), + }); + return ( - {children} - + ); }); diff --git a/packages/mui-material/src/Menu/Menu.spec.tsx b/packages/mui-material/src/Menu/Menu.spec.tsx new file mode 100644 index 00000000000000..933c42822f18b1 --- /dev/null +++ b/packages/mui-material/src/Menu/Menu.spec.tsx @@ -0,0 +1,24 @@ +import * as React from 'react'; +import Menu from '@mui/material/Menu'; + +; diff --git a/packages/mui-material/src/Menu/Menu.test.js b/packages/mui-material/src/Menu/Menu.test.js index 1d9ca77a1861cd..e8a735d551200c 100644 --- a/packages/mui-material/src/Menu/Menu.test.js +++ b/packages/mui-material/src/Menu/Menu.test.js @@ -30,6 +30,10 @@ describe('', () => { paper: { expectedClassName: classes.paper, }, + list: { + expectedClassName: classes.list, + testWithElement: null, // already tested with `testWithComponent` + }, }, testDeepOverrides: { slotName: 'list', slotClassName: classes.list }, testRootOverrides: { slotName: 'root', slotClassName: classes.root }, @@ -217,33 +221,63 @@ describe('', () => { expect(screen.getByRole('menu')).not.toHaveFocus(); }); - it('should call TransitionProps.onEntering', () => { + it('should call slotProps.transition.onEntering', () => { const onEnteringSpy = spy(); render( , ); expect(onEnteringSpy.callCount).to.equal(1); }); - it('should call TransitionProps.onEntering, disableAutoFocusItem', () => { + it('should call slotProps.transition.onEntering, disableAutoFocusItem', () => { const onEnteringSpy = spy(); render( , ); expect(onEnteringSpy.callCount).to.equal(1); }); + // TODO: remove in v7 + describe('legacy TransitionProps', () => { + it('should call TransitionProps.onEntering', () => { + const onEnteringSpy = spy(); + render( + , + ); + + expect(onEnteringSpy.callCount).to.equal(1); + }); + + it('should call TransitionProps.onEntering, disableAutoFocusItem', () => { + const onEnteringSpy = spy(); + render( + , + ); + + expect(onEnteringSpy.callCount).to.equal(1); + }); + }); + it('should call onClose on tab', () => { function MenuItem(props) { const { autoFocus, children } = props; From 9554f3377ab7bfebc8d197a842cbf6cec12e75b7 Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Thu, 2 Jan 2025 14:49:05 +0700 Subject: [PATCH 02/10] add menu props codemod --- .../src/deprecations/all/deprecations-all.js | 2 + .../src/deprecations/menu-props/index.js | 1 + .../src/deprecations/menu-props/menu-props.js | 27 +++++++++++ .../menu-props/menu-props.test.js | 16 +++++++ .../menu-props/test-cases/actual.js | 34 ++++++++++++++ .../menu-props/test-cases/expected.js | 47 +++++++++++++++++++ .../menu-props/test-cases/theme.actual.js | 20 ++++++++ .../menu-props/test-cases/theme.expected.js | 22 +++++++++ 8 files changed, 169 insertions(+) create mode 100644 packages/mui-codemod/src/deprecations/menu-props/index.js create mode 100644 packages/mui-codemod/src/deprecations/menu-props/menu-props.js create mode 100644 packages/mui-codemod/src/deprecations/menu-props/menu-props.test.js create mode 100644 packages/mui-codemod/src/deprecations/menu-props/test-cases/actual.js create mode 100644 packages/mui-codemod/src/deprecations/menu-props/test-cases/expected.js create mode 100644 packages/mui-codemod/src/deprecations/menu-props/test-cases/theme.actual.js create mode 100644 packages/mui-codemod/src/deprecations/menu-props/test-cases/theme.expected.js diff --git a/packages/mui-codemod/src/deprecations/all/deprecations-all.js b/packages/mui-codemod/src/deprecations/all/deprecations-all.js index c6a16ef48d29ba..dfb1de2ebdaac2 100644 --- a/packages/mui-codemod/src/deprecations/all/deprecations-all.js +++ b/packages/mui-codemod/src/deprecations/all/deprecations-all.js @@ -29,6 +29,7 @@ import transformTabClasses from '../tab-classes'; import transformToggleButtonGroupClasses from '../toggle-button-group-classes'; import transformTooltipProps from '../tooltip-props'; import transformTablePaginationProps from '../table-pagination-props'; +import transformMenuProps from '../menu-props'; /** * @param {import('jscodeshift').FileInfo} file @@ -66,6 +67,7 @@ export default function deprecationsAll(file, api, options) { file.source = transformToggleButtonGroupClasses(file, api, options); file.source = transformTooltipProps(file, api, options); file.source = transformTablePaginationProps(file, api, options); + file.source = transformMenuProps(file, api, options); return file.source; } diff --git a/packages/mui-codemod/src/deprecations/menu-props/index.js b/packages/mui-codemod/src/deprecations/menu-props/index.js new file mode 100644 index 00000000000000..c8c171018fcccd --- /dev/null +++ b/packages/mui-codemod/src/deprecations/menu-props/index.js @@ -0,0 +1 @@ +export { default } from './menu-props'; diff --git a/packages/mui-codemod/src/deprecations/menu-props/menu-props.js b/packages/mui-codemod/src/deprecations/menu-props/menu-props.js new file mode 100644 index 00000000000000..c1982f116b41db --- /dev/null +++ b/packages/mui-codemod/src/deprecations/menu-props/menu-props.js @@ -0,0 +1,27 @@ +import movePropIntoSlotProps from '../utils/movePropIntoSlotProps'; + +/** + * @param {import('jscodeshift').FileInfo} file + * @param {import('jscodeshift').API} api + */ +export default function transformer(file, api, options) { + const j = api.jscodeshift; + const root = j(file.source); + const printOptions = options.printOptions; + + movePropIntoSlotProps(j, { + root, + componentName: 'Menu', + propName: 'MenuListProps', + slotName: 'list', + }); + + movePropIntoSlotProps(j, { + root, + componentName: 'Menu', + propName: 'TransitionProps', + slotName: 'transition', + }); + + return root.toSource(printOptions); +} diff --git a/packages/mui-codemod/src/deprecations/menu-props/menu-props.test.js b/packages/mui-codemod/src/deprecations/menu-props/menu-props.test.js new file mode 100644 index 00000000000000..c3e716c43bb381 --- /dev/null +++ b/packages/mui-codemod/src/deprecations/menu-props/menu-props.test.js @@ -0,0 +1,16 @@ +import { describeJscodeshiftTransform } from '../../../testUtils'; +import transform from './menu-props'; + +describe('@mui/codemod', () => { + describe('deprecations', () => { + describeJscodeshiftTransform({ + transform, + transformName: 'menu-props', + dirname: __dirname, + testCases: [ + { actual: '/test-cases/actual.js', expected: '/test-cases/expected.js' }, + { actual: '/test-cases/theme.actual.js', expected: '/test-cases/theme.expected.js' }, + ], + }); + }); +}); diff --git a/packages/mui-codemod/src/deprecations/menu-props/test-cases/actual.js b/packages/mui-codemod/src/deprecations/menu-props/test-cases/actual.js new file mode 100644 index 00000000000000..271c50275d5eb7 --- /dev/null +++ b/packages/mui-codemod/src/deprecations/menu-props/test-cases/actual.js @@ -0,0 +1,34 @@ +import Menu from '@mui/material/Menu'; +import { Menu as MyMenu } from '@mui/material'; + +; + +; + +; + +; + +; diff --git a/packages/mui-codemod/src/deprecations/menu-props/test-cases/expected.js b/packages/mui-codemod/src/deprecations/menu-props/test-cases/expected.js new file mode 100644 index 00000000000000..85f63e5be187ac --- /dev/null +++ b/packages/mui-codemod/src/deprecations/menu-props/test-cases/expected.js @@ -0,0 +1,47 @@ +import Menu from '@mui/material/Menu'; +import { Menu as MyMenu } from '@mui/material'; + +; + +; + +; + +; + +; diff --git a/packages/mui-codemod/src/deprecations/menu-props/test-cases/theme.actual.js b/packages/mui-codemod/src/deprecations/menu-props/test-cases/theme.actual.js new file mode 100644 index 00000000000000..4ea40d0d3c6f92 --- /dev/null +++ b/packages/mui-codemod/src/deprecations/menu-props/test-cases/theme.actual.js @@ -0,0 +1,20 @@ +fn({ + MuiMenu: { + defaultProps: { + MenuListProps: { disablePadding: true }, + TransitionProps: { timeout: 200 }, + }, + }, +}); + +fn({ + MuiMenu: { + defaultProps: { + MenuListProps: { disablePadding: true }, + TransitionProps: { timeout: 200 }, + slotProps: { + root: { disablePortal: true }, + }, + }, + }, +}); diff --git a/packages/mui-codemod/src/deprecations/menu-props/test-cases/theme.expected.js b/packages/mui-codemod/src/deprecations/menu-props/test-cases/theme.expected.js new file mode 100644 index 00000000000000..d66570979c3a11 --- /dev/null +++ b/packages/mui-codemod/src/deprecations/menu-props/test-cases/theme.expected.js @@ -0,0 +1,22 @@ +fn({ + MuiMenu: { + defaultProps: { + slotProps: { + list: { disablePadding: true }, + transition: { timeout: 200 } + } + }, + }, +}); + +fn({ + MuiMenu: { + defaultProps: { + slotProps: { + root: { disablePortal: true }, + list: { disablePadding: true }, + transition: { timeout: 200 } + } + }, + }, +}); From 71c97c85f208c7e37d8d0c3133957a9d166df7ed Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Thu, 2 Jan 2025 15:10:30 +0700 Subject: [PATCH 03/10] update proptypes and api --- docs/pages/material-ui/api/menu.json | 55 ++++++++++++++++------- docs/translations/api-docs/menu/menu.json | 19 ++++---- packages/mui-material/src/Menu/Menu.d.ts | 20 +++++++-- packages/mui-material/src/Menu/Menu.js | 14 ++++++ 4 files changed, 78 insertions(+), 30 deletions(-) diff --git a/docs/pages/material-ui/api/menu.json b/docs/pages/material-ui/api/menu.json index c44d55a25cd264..35976706e3a1d1 100644 --- a/docs/pages/material-ui/api/menu.json +++ b/docs/pages/material-ui/api/menu.json @@ -6,7 +6,12 @@ "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" }, "additionalInfo": { "cssApi": true } }, "disableAutoFocusItem": { "type": { "name": "bool" }, "default": "false" }, - "MenuListProps": { "type": { "name": "object" }, "default": "{}" }, + "MenuListProps": { + "type": { "name": "object" }, + "default": "{}", + "deprecated": true, + "deprecationInfo": "use the slotProps.list prop instead. This prop will be removed in v7. See Migrating from deprecated APIs for more details." + }, "onClose": { "type": { "name": "func" }, "signature": { @@ -18,12 +23,15 @@ "slotProps": { "type": { "name": "shape", - "description": "{ paper?: func
| object, root?: func
| object }" + "description": "{ list?: func
| object, paper?: func
| object, root?: func
| object, transition?: func
| object }" }, "default": "{}" }, "slots": { - "type": { "name": "shape", "description": "{ paper?: elementType, root?: elementType }" }, + "type": { + "name": "shape", + "description": "{ list?: elementType, paper?: elementType, root?: elementType, transition?: elementType }" + }, "default": "{}" }, "sx": { @@ -33,6 +41,7 @@ }, "additionalInfo": { "sx": true } }, + "TransitionComponent": { "type": { "name": "elementType" }, "default": "Grow" }, "transitionDuration": { "type": { "name": "union", @@ -40,7 +49,12 @@ }, "default": "'auto'" }, - "TransitionProps": { "type": { "name": "object" }, "default": "{}" }, + "TransitionProps": { + "type": { "name": "object" }, + "default": "{}", + "deprecated": true, + "deprecationInfo": "use the slotProps.transition prop instead. This prop will be removed in v7. See Migrating from deprecated APIs for more details." + }, "variant": { "type": { "name": "enum", "description": "'menu'
| 'selectedMenu'" }, "default": "'selectedMenu'" @@ -48,26 +62,33 @@ }, "name": "Menu", "imports": ["import Menu from '@mui/material/Menu';", "import { Menu } from '@mui/material';"], - "classes": [ + "slots": [ + { + "name": "root", + "description": "The component used for the popper.", + "default": "Modal", + "class": "MuiMenu-root" + }, { - "key": "list", - "className": "MuiMenu-list", - "description": "Styles applied to the List component via `MenuList`.", - "isGlobal": false + "name": "paper", + "description": "The component used for the paper.", + "default": "Paper", + "class": "MuiMenu-paper" }, { - "key": "paper", - "className": "MuiMenu-paper", - "description": "Styles applied to the Paper component.", - "isGlobal": false + "name": "transition", + "description": "The component used for the transition.\n[Follow this guide](https://mui.com/material-ui/transitions/#transitioncomponent-prop) to learn more about the requirements for this component.", + "default": "Grow", + "class": null }, { - "key": "root", - "className": "MuiMenu-root", - "description": "Styles applied to the root element.", - "isGlobal": false + "name": "list", + "description": "The component used for the list.", + "default": "MenuList", + "class": "MuiMenu-list" } ], + "classes": [], "spread": true, "themeDefaultProps": false, "muiName": "MuiMenu", diff --git a/docs/translations/api-docs/menu/menu.json b/docs/translations/api-docs/menu/menu.json index afd676d6d50a63..c9092486b83af6 100644 --- a/docs/translations/api-docs/menu/menu.json +++ b/docs/translations/api-docs/menu/menu.json @@ -31,6 +31,9 @@ "sx": { "description": "The system prop that allows defining system overrides as well as additional CSS styles." }, + "TransitionComponent": { + "description": "The component used for the transition. Follow this guide to learn more about the requirements for this component." + }, "transitionDuration": { "description": "The length of the transition in ms, or 'auto'" }, @@ -41,15 +44,11 @@ "description": "The variant to use. Use menu to prevent selected items from impacting the initial focus." } }, - "classDescriptions": { - "list": { - "description": "Styles applied to {{nodeName}}.", - "nodeName": "the List component via MenuList" - }, - "paper": { - "description": "Styles applied to {{nodeName}}.", - "nodeName": "the Paper component" - }, - "root": { "description": "Styles applied to the root element." } + "classDescriptions": {}, + "slotDescriptions": { + "list": "The component used for the list.", + "paper": "The component used for the paper.", + "root": "The component used for the popper.", + "transition": "The component used for the transition. Follow this guide to learn more about the requirements for this component." } } diff --git a/packages/mui-material/src/Menu/Menu.d.ts b/packages/mui-material/src/Menu/Menu.d.ts index d87ce36f06f2df..ec15cf64c8e419 100644 --- a/packages/mui-material/src/Menu/Menu.d.ts +++ b/packages/mui-material/src/Menu/Menu.d.ts @@ -4,7 +4,7 @@ import { InternalStandardProps as StandardProps } from '..'; import { PaperProps } from '../Paper'; import { PopoverProps } from '../Popover'; import { MenuListProps } from '../MenuList'; -import { ModalOwnProps } from '../Modal'; +import { ModalProps } from '../Modal'; import { Theme } from '../styles'; import { TransitionProps } from '../transitions/transition'; import { MenuClasses } from './menuClasses'; @@ -20,18 +20,32 @@ export interface MenuListSlotPropsOverrides {} export interface MenuSlots { /** - * The content of the component. + * The component used for the popper. + * @default Modal */ root: React.ElementType; + /** + * The component used for the paper. + * @default Paper + */ paper: React.ElementType; + /** + * The component used for the transition. + * [Follow this guide](https://mui.com/material-ui/transitions/#transitioncomponent-prop) to learn more about the requirements for this component. + * @default Grow + */ transition: React.ElementType; + /** + * The component used for the list. + * @default MenuList + */ list: React.ElementType; } export type MenuSlotsAndSlotProps = CreateSlotsAndSlotProps< MenuSlots, { - root: SlotProps, MenuRootSlotPropsOverrides, MenuOwnerState>; + root: SlotProps, MenuRootSlotPropsOverrides, MenuOwnerState>; paper: SlotProps, MenuPaperSlotPropsOverrides, MenuOwnerState>; transition: SlotProps< React.ElementType, diff --git a/packages/mui-material/src/Menu/Menu.js b/packages/mui-material/src/Menu/Menu.js index f000722542a1c8..4ac48b0aa5f9ff 100644 --- a/packages/mui-material/src/Menu/Menu.js +++ b/packages/mui-material/src/Menu/Menu.js @@ -80,6 +80,7 @@ const Menu = React.forwardRef(function Menu(inProps, ref) { PaperProps = {}, PopoverClasses, transitionDuration = 'auto', + TransitionComponent, TransitionProps = {}, variant = 'selectedMenu', slots = {}, @@ -209,6 +210,7 @@ const Menu = React.forwardRef(function Menu(inProps, ref) { ref={ref} transitionDuration={transitionDuration} TransitionProps={{ onEntering: handleEntering, ...transitionProps }} + TransitionComponent={slots.transition ?? TransitionComponent} ownerState={ownerState} {...other} classes={PopoverClasses} @@ -270,6 +272,7 @@ Menu.propTypes /* remove-proptypes */ = { disableAutoFocusItem: PropTypes.bool, /** * Props applied to the [`MenuList`](https://mui.com/material-ui/api/menu-list/) element. + * @deprecated use the `slotProps.list` prop instead. This prop will be removed in v7. See [Migrating from deprecated APIs](https://mui.com/material-ui/migration/migrating-from-deprecated-apis/) for more details. * @default {} */ MenuListProps: PropTypes.object, @@ -297,16 +300,20 @@ Menu.propTypes /* remove-proptypes */ = { * @default {} */ slotProps: PropTypes.shape({ + list: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), paper: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), root: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), + transition: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), }), /** * The components used for each slot inside. * @default {} */ slots: PropTypes.shape({ + list: PropTypes.elementType, paper: PropTypes.elementType, root: PropTypes.elementType, + transition: PropTypes.elementType, }), /** * The system prop that allows defining system overrides as well as additional CSS styles. @@ -316,6 +323,12 @@ Menu.propTypes /* remove-proptypes */ = { PropTypes.func, PropTypes.object, ]), + /** + * The component used for the transition. + * [Follow this guide](https://mui.com/material-ui/transitions/#transitioncomponent-prop) to learn more about the requirements for this component. + * @default Grow + */ + TransitionComponent: PropTypes.elementType, /** * The length of the transition in `ms`, or 'auto' * @default 'auto' @@ -332,6 +345,7 @@ Menu.propTypes /* remove-proptypes */ = { /** * Props applied to the transition element. * By default, the element is based on this [`Transition`](https://reactcommunity.org/react-transition-group/transition/) component. + * @deprecated use the `slotProps.transition` prop instead. This prop will be removed in v7. See [Migrating from deprecated APIs](https://mui.com/material-ui/migration/migrating-from-deprecated-apis/) for more details. * @default {} */ TransitionProps: PropTypes.object, From 15c015b5f581f834fe4f4312dc0ce54934b2143e Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Thu, 2 Jan 2025 15:12:53 +0700 Subject: [PATCH 04/10] update codemod to transform TransitionComponent --- .../src/deprecations/menu-props/menu-props.js | 8 ++++++++ .../menu-props/test-cases/actual.js | 20 ++++++++++++++++--- .../menu-props/test-cases/expected.js | 18 ++++++++++++++++- .../menu-props/test-cases/theme.actual.js | 2 ++ .../menu-props/test-cases/theme.expected.js | 8 ++++++++ 5 files changed, 52 insertions(+), 4 deletions(-) diff --git a/packages/mui-codemod/src/deprecations/menu-props/menu-props.js b/packages/mui-codemod/src/deprecations/menu-props/menu-props.js index c1982f116b41db..f63fa7bae12e07 100644 --- a/packages/mui-codemod/src/deprecations/menu-props/menu-props.js +++ b/packages/mui-codemod/src/deprecations/menu-props/menu-props.js @@ -1,3 +1,4 @@ +import movePropIntoSlots from '../utils/movePropIntoSlots'; import movePropIntoSlotProps from '../utils/movePropIntoSlotProps'; /** @@ -16,6 +17,13 @@ export default function transformer(file, api, options) { slotName: 'list', }); + movePropIntoSlots(j, { + root, + componentName: 'Menu', + propName: 'TransitionComponent', + slotName: 'transition', + }); + movePropIntoSlotProps(j, { root, componentName: 'Menu', diff --git a/packages/mui-codemod/src/deprecations/menu-props/test-cases/actual.js b/packages/mui-codemod/src/deprecations/menu-props/test-cases/actual.js index 271c50275d5eb7..17a922ade4a592 100644 --- a/packages/mui-codemod/src/deprecations/menu-props/test-cases/actual.js +++ b/packages/mui-codemod/src/deprecations/menu-props/test-cases/actual.js @@ -1,9 +1,14 @@ import Menu from '@mui/material/Menu'; import { Menu as MyMenu } from '@mui/material'; -; +; ; ; -; +; -; +; diff --git a/packages/mui-codemod/src/deprecations/menu-props/test-cases/expected.js b/packages/mui-codemod/src/deprecations/menu-props/test-cases/expected.js index 85f63e5be187ac..dbeb1e029f5414 100644 --- a/packages/mui-codemod/src/deprecations/menu-props/test-cases/expected.js +++ b/packages/mui-codemod/src/deprecations/menu-props/test-cases/expected.js @@ -5,6 +5,9 @@ import { Menu as MyMenu } from '@mui/material'; slotProps={{ list: { disablePadding: true }, transition: { timeout: 200 } + }} + slots={{ + transition: CustomTransition }} />; ; ; ; -; +; diff --git a/packages/mui-codemod/src/deprecations/menu-props/test-cases/theme.actual.js b/packages/mui-codemod/src/deprecations/menu-props/test-cases/theme.actual.js index 4ea40d0d3c6f92..29889ee6e1522a 100644 --- a/packages/mui-codemod/src/deprecations/menu-props/test-cases/theme.actual.js +++ b/packages/mui-codemod/src/deprecations/menu-props/test-cases/theme.actual.js @@ -2,6 +2,7 @@ fn({ MuiMenu: { defaultProps: { MenuListProps: { disablePadding: true }, + TransitionComponent: CustomTransition, TransitionProps: { timeout: 200 }, }, }, @@ -10,6 +11,7 @@ fn({ fn({ MuiMenu: { defaultProps: { + TransitionComponent: CustomTransition, MenuListProps: { disablePadding: true }, TransitionProps: { timeout: 200 }, slotProps: { diff --git a/packages/mui-codemod/src/deprecations/menu-props/test-cases/theme.expected.js b/packages/mui-codemod/src/deprecations/menu-props/test-cases/theme.expected.js index d66570979c3a11..fa88e0b9e4aca7 100644 --- a/packages/mui-codemod/src/deprecations/menu-props/test-cases/theme.expected.js +++ b/packages/mui-codemod/src/deprecations/menu-props/test-cases/theme.expected.js @@ -4,6 +4,10 @@ fn({ slotProps: { list: { disablePadding: true }, transition: { timeout: 200 } + }, + + slots: { + transition: CustomTransition } }, }, @@ -16,6 +20,10 @@ fn({ root: { disablePortal: true }, list: { disablePadding: true }, transition: { timeout: 200 } + }, + + slots: { + transition: CustomTransition } }, }, From 9e82abdd944e9e3723a099dd2d0200f070a542d8 Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Thu, 2 Jan 2025 16:13:45 +0700 Subject: [PATCH 05/10] remove deprecated prop usage --- packages/mui-material/src/Menu/Menu.js | 7 ++++++- packages/mui-material/src/Select/SelectInput.js | 16 ++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/packages/mui-material/src/Menu/Menu.js b/packages/mui-material/src/Menu/Menu.js index 4ac48b0aa5f9ff..ae3c1cc433c692 100644 --- a/packages/mui-material/src/Menu/Menu.js +++ b/packages/mui-material/src/Menu/Menu.js @@ -166,6 +166,11 @@ const Menu = React.forwardRef(function Menu(inProps, ref) { } }); + const externalForwardedProps = { + slots, + slotProps: { ...slotProps, list: slotProps.list || MenuListProps }, + }; + const PaperSlot = slots.paper ?? MenuPaper; const paperExternalSlotProps = slotProps.paper ?? PaperProps; @@ -185,7 +190,7 @@ const Menu = React.forwardRef(function Menu(inProps, ref) { const [ListSlot, listSlotProps] = useSlot('list', { elementType: MenuMenuList, - externalForwardedProps: { slots, slotProps }, + externalForwardedProps, ownerState, className: clsx(classes.list, MenuListProps.className), }); diff --git a/packages/mui-material/src/Select/SelectInput.js b/packages/mui-material/src/Select/SelectInput.js index fd48bd5d44b08d..076fc8ea056c5f 100644 --- a/packages/mui-material/src/Select/SelectInput.js +++ b/packages/mui-material/src/Select/SelectInput.js @@ -556,16 +556,16 @@ const SelectInput = React.forwardRef(function SelectInput(props, ref) { horizontal: 'center', }} {...MenuProps} - MenuListProps={{ - 'aria-labelledby': labelId, - role: 'listbox', - 'aria-multiselectable': multiple ? 'true' : undefined, - disableListWrap: true, - id: listboxId, - ...MenuProps.MenuListProps, - }} slotProps={{ ...MenuProps.slotProps, + list: { + 'aria-labelledby': labelId, + role: 'listbox', + 'aria-multiselectable': multiple ? 'true' : undefined, + disableListWrap: true, + id: listboxId, + ...MenuProps.MenuListProps, + }, paper: { ...paperProps, style: { From 8b43b0e08a9e7a3bd370b76e216cf2a8b97d9bad Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Thu, 9 Jan 2025 13:49:31 +0700 Subject: [PATCH 06/10] apply suggestion --- packages/mui-material/src/Menu/Menu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mui-material/src/Menu/Menu.js b/packages/mui-material/src/Menu/Menu.js index ae3c1cc433c692..d8e3640eb3bc6c 100644 --- a/packages/mui-material/src/Menu/Menu.js +++ b/packages/mui-material/src/Menu/Menu.js @@ -168,7 +168,7 @@ const Menu = React.forwardRef(function Menu(inProps, ref) { const externalForwardedProps = { slots, - slotProps: { ...slotProps, list: slotProps.list || MenuListProps }, + slotProps: { list: MenuListProps, ...slotProps }, }; const PaperSlot = slots.paper ?? MenuPaper; From e55efb6e936304769a08c247a1a1a38456bcb7d4 Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Thu, 9 Jan 2025 13:58:29 +0700 Subject: [PATCH 07/10] add migration doc --- .../migrating-from-deprecated-apis.md | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/docs/data/material/migration/migrating-from-deprecated-apis/migrating-from-deprecated-apis.md b/docs/data/material/migration/migrating-from-deprecated-apis/migrating-from-deprecated-apis.md index 24c27c33051d02..81f13ca20fdd6a 100644 --- a/docs/data/material/migration/migrating-from-deprecated-apis/migrating-from-deprecated-apis.md +++ b/docs/data/material/migration/migrating-from-deprecated-apis/migrating-from-deprecated-apis.md @@ -1375,6 +1375,36 @@ Here's how to migrate: }, ``` +## Menu + +Use the [codemod](https://github.com/mui/material-ui/tree/HEAD/packages/mui-codemod#menu-props) below to migrate the code as described in the following sections: + +```bash +npx @mui/codemod@latest deprecations/menu-props +``` + +### MenuListProps + +The Menu's `MenuListProps` prop was deprecated in favor of `slotProps.list`: + +```diff + +``` + +### TransitionProps + +The Menu's `TransitionProps` prop was deprecated in favor of `slotProps.transition`: + +```diff + +``` + ## Modal Use the [codemod](https://github.com/mui/material-ui/tree/HEAD/packages/mui-codemod#modal-props) below to migrate the code as described in the following sections: From c3c193a3576a215684edff99d7e3ff9f639fe783 Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Fri, 10 Jan 2025 14:39:32 +0700 Subject: [PATCH 08/10] use TransitionComponent from other to prevent propTypes generation --- packages/mui-material/src/Menu/Menu.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/mui-material/src/Menu/Menu.js b/packages/mui-material/src/Menu/Menu.js index d8e3640eb3bc6c..c47e9f50a0ed64 100644 --- a/packages/mui-material/src/Menu/Menu.js +++ b/packages/mui-material/src/Menu/Menu.js @@ -80,7 +80,6 @@ const Menu = React.forwardRef(function Menu(inProps, ref) { PaperProps = {}, PopoverClasses, transitionDuration = 'auto', - TransitionComponent, TransitionProps = {}, variant = 'selectedMenu', slots = {}, @@ -215,9 +214,9 @@ const Menu = React.forwardRef(function Menu(inProps, ref) { ref={ref} transitionDuration={transitionDuration} TransitionProps={{ onEntering: handleEntering, ...transitionProps }} - TransitionComponent={slots.transition ?? TransitionComponent} ownerState={ownerState} {...other} + TransitionComponent={slots.transition ?? other.TransitionComponent} classes={PopoverClasses} > Date: Thu, 6 Feb 2025 17:32:03 +0700 Subject: [PATCH 09/10] update Menu --- docs/pages/material-ui/api/menu.json | 21 +++++--- docs/translations/api-docs/menu/menu.json | 6 +-- packages/mui-material/src/Menu/Menu.d.ts | 57 ++++++++++++++++----- packages/mui-material/src/Menu/Menu.js | 62 +++++++++++++++-------- 4 files changed, 98 insertions(+), 48 deletions(-) diff --git a/docs/pages/material-ui/api/menu.json b/docs/pages/material-ui/api/menu.json index f2307a43e50292..543e9f02cbbc04 100644 --- a/docs/pages/material-ui/api/menu.json +++ b/docs/pages/material-ui/api/menu.json @@ -23,14 +23,14 @@ "slotProps": { "type": { "name": "shape", - "description": "{ backdrop?: func
| object, paper?: func
| object, root?: func
| object, transition?: func
| object }" + "description": "{ backdrop?: func
| object, list?: func
| object, paper?: func
| object, root?: func
| object, transition?: func
| object }" }, "default": "{}" }, "slots": { "type": { "name": "shape", - "description": "{ backdrop?: elementType, paper?: elementType, root?: elementType, transition?: elementType }" + "description": "{ backdrop?: elementType, list?: elementType, paper?: elementType, root?: elementType, transition?: elementType }" }, "default": "{}" }, @@ -41,7 +41,6 @@ }, "additionalInfo": { "sx": true } }, - "TransitionComponent": { "type": { "name": "elementType" }, "default": "Grow" }, "transitionDuration": { "type": { "name": "union", @@ -75,17 +74,23 @@ "default": "Paper", "class": "MuiMenu-paper" }, + { + "name": "list", + "description": "The component used for the list.", + "default": "MenuList", + "class": "MuiMenu-list" + }, { "name": "transition", - "description": "The component used for the transition.\n[Follow this guide](https://mui.com/material-ui/transitions/#transitioncomponent-prop) to learn more about the requirements for this component.", + "description": "The component used for the transition slot.", "default": "Grow", "class": null }, { - "name": "list", - "description": "The component used for the list.", - "default": "MenuList", - "class": "MuiMenu-list" + "name": "backdrop", + "description": "The component used for the backdrop slot.", + "default": "Backdrop", + "class": null } ], "classes": [], diff --git a/docs/translations/api-docs/menu/menu.json b/docs/translations/api-docs/menu/menu.json index c9092486b83af6..cf5c9609d5fe73 100644 --- a/docs/translations/api-docs/menu/menu.json +++ b/docs/translations/api-docs/menu/menu.json @@ -31,9 +31,6 @@ "sx": { "description": "The system prop that allows defining system overrides as well as additional CSS styles." }, - "TransitionComponent": { - "description": "The component used for the transition. Follow this guide to learn more about the requirements for this component." - }, "transitionDuration": { "description": "The length of the transition in ms, or 'auto'" }, @@ -46,9 +43,10 @@ }, "classDescriptions": {}, "slotDescriptions": { + "backdrop": "The component used for the backdrop slot.", "list": "The component used for the list.", "paper": "The component used for the paper.", "root": "The component used for the popper.", - "transition": "The component used for the transition. Follow this guide to learn more about the requirements for this component." + "transition": "The component used for the transition slot." } } diff --git a/packages/mui-material/src/Menu/Menu.d.ts b/packages/mui-material/src/Menu/Menu.d.ts index a63f8c0aa48901..eaa0add5b9f2aa 100644 --- a/packages/mui-material/src/Menu/Menu.d.ts +++ b/packages/mui-material/src/Menu/Menu.d.ts @@ -2,13 +2,20 @@ import * as React from 'react'; import { SxProps } from '@mui/system'; import { InternalStandardProps as StandardProps } from '..'; import { PaperProps } from '../Paper'; -import { PopoverProps } from '../Popover'; +import { + PopoverProps, + PopoverSlots, + PopoverOwnerState, + PopoverBackdropSlotPropsOverrides, + PopoverTransitionSlotPropsOverrides, +} from '../Popover'; import { MenuListProps } from '../MenuList'; import { ModalProps } from '../Modal'; +import { BackdropProps } from '../Backdrop'; import { Theme } from '../styles'; import { TransitionProps } from '../transitions/transition'; import { MenuClasses } from './menuClasses'; -import { CreateSlotsAndSlotProps, SlotProps } from '../utils/types'; +import { CreateSlotsAndSlotProps, SlotComponentProps, SlotProps } from '../utils/types'; export interface MenuRootSlotPropsOverrides {} @@ -18,7 +25,9 @@ export interface MenuTransitionSlotPropsOverrides {} export interface MenuListSlotPropsOverrides {} -export interface MenuSlots { +export interface MenuBackdropSlotPropsOverrides {} + +export interface MenuSlots extends Pick { /** * The component used for the popper. * @default Modal @@ -29,12 +38,6 @@ export interface MenuSlots { * @default Paper */ paper: React.ElementType; - /** - * The component used for the transition. - * [Follow this guide](https://mui.com/material-ui/transitions/#transitioncomponent-prop) to learn more about the requirements for this component. - * @default Grow - */ - transition: React.ElementType; /** * The component used for the list. * @default MenuList @@ -45,14 +48,40 @@ export interface MenuSlots { export type MenuSlotsAndSlotProps = CreateSlotsAndSlotProps< MenuSlots, { + /** + * Props forwarded to the root slot. + * By default, the avaible props are based on the [Popover](https://mui.com/material-ui/api/popover/#props) component. + */ root: SlotProps, MenuRootSlotPropsOverrides, MenuOwnerState>; + /** + * Props forwarded to the paper slot. + * By default, the avaible props are based on the [Paper](https://mui.com/material-ui/api/paper/#props) component. + */ paper: SlotProps, MenuPaperSlotPropsOverrides, MenuOwnerState>; - transition: SlotProps< + /** + * Props forwarded to the list slot. + * By default, the avaible props are based on the [MenuList](https://mui.com/material-ui/api/menu-list/#props) component. + */ + list: SlotProps, MenuListSlotPropsOverrides, MenuOwnerState>; + /** + * Props forwarded to the transition slot. + * By default, the avaible 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, - MenuTransitionSlotPropsOverrides, - MenuOwnerState + PopoverTransitionSlotPropsOverrides, + PopoverOwnerState + >; + /** + * Props forwarded to the backdrop slot. + * By default, the avaible props are based on the [Backdrop](https://mui.com/material-ui/api/backdrop/#props) component. + */ + backdrop: SlotProps< + React.ElementType, + PopoverBackdropSlotPropsOverrides, + PopoverOwnerState >; - list: SlotProps, MenuListSlotPropsOverrides, MenuOwnerState>; } >; @@ -132,7 +161,7 @@ export interface MenuProps variant?: 'menu' | 'selectedMenu'; } -export interface MenuOwnerState extends MenuProps {} +export interface MenuOwnerState extends Omit {} export declare const MenuPaper: React.FC; diff --git a/packages/mui-material/src/Menu/Menu.js b/packages/mui-material/src/Menu/Menu.js index 6ee743669c07e7..c58fd6ff02173f 100644 --- a/packages/mui-material/src/Menu/Menu.js +++ b/packages/mui-material/src/Menu/Menu.js @@ -80,7 +80,7 @@ const Menu = React.forwardRef(function Menu(inProps, ref) { PaperProps = {}, PopoverClasses, transitionDuration = 'auto', - TransitionProps = {}, + TransitionProps: { onEntering, ...TransitionProps } = {}, variant = 'selectedMenu', slots = {}, slotProps = {}, @@ -89,8 +89,6 @@ const Menu = React.forwardRef(function Menu(inProps, ref) { const isRtl = useRtl(); - const { onEntering, ...transitionProps } = slotProps.transition ?? TransitionProps; - const ownerState = { ...props, autoFocus, @@ -167,12 +165,14 @@ const Menu = React.forwardRef(function Menu(inProps, ref) { const externalForwardedProps = { slots, - slotProps: { list: MenuListProps, ...slotProps }, + slotProps: { + list: MenuListProps, + transition: TransitionProps, + paper: PaperProps, + ...slotProps, + }, }; - const PaperSlot = slots.paper ?? MenuPaper; - const paperExternalSlotProps = slotProps.paper ?? PaperProps; - const rootSlotProps = useSlotProps({ elementType: slots.root, externalSlotProps: slotProps.root, @@ -180,18 +180,27 @@ const Menu = React.forwardRef(function Menu(inProps, ref) { className: [classes.root, className], }); - const paperSlotProps = useSlotProps({ - elementType: PaperSlot, - externalSlotProps: paperExternalSlotProps, - ownerState, + const [PaperSlot, paperSlotProps] = useSlot('paper', { className: classes.paper, + elementType: MenuPaper, + externalForwardedProps, + shouldForwardComponentProp: true, + ownerState, }); const [ListSlot, listSlotProps] = useSlot('list', { + className: clsx(classes.list, MenuListProps.className), elementType: MenuMenuList, + shouldForwardComponentProp: true, externalForwardedProps, + getSlotProps: (handlers) => ({ + ...handlers, + onKeyDown: (event) => { + handleListKeyDown(event); + handlers.onKeyDown?.(event); + }, + }), ownerState, - className: clsx(classes.list, MenuListProps.className), }); return ( @@ -203,24 +212,37 @@ const Menu = React.forwardRef(function Menu(inProps, ref) { }} transformOrigin={isRtl ? RTL_ORIGIN : LTR_ORIGIN} slots={{ - paper: PaperSlot, root: slots.root, + paper: PaperSlot, + backdrop: slots.backdrop, + transition: slots.transition, }} slotProps={{ root: rootSlotProps, paper: paperSlotProps, + backdrop: slotProps.backdrop, + transition: (innerState) => { + const transitionProps = + typeof slotProps.transition === 'function' + ? slotProps.transition(innerState) + : slotProps.transition; + return { + ...transitionProps, + onEntering: (...args) => { + handleEntering(...args); + transitionProps?.onEntering?.(...args); + }, + }; + }, }} open={open} ref={ref} transitionDuration={transitionDuration} - TransitionProps={{ onEntering: handleEntering, ...transitionProps }} ownerState={ownerState} {...other} - TransitionComponent={slots.transition ?? other.TransitionComponent} classes={PopoverClasses} > Date: Thu, 6 Feb 2025 17:47:15 +0700 Subject: [PATCH 10/10] fix tests --- packages/mui-material/src/Menu/Menu.d.ts | 30 +++++++------ packages/mui-material/src/Menu/Menu.js | 28 ++++++------ packages/mui-material/src/Menu/Menu.spec.tsx | 47 +++++++++++++++++++- packages/mui-material/src/Menu/Menu.test.js | 19 ++++++++ 4 files changed, 97 insertions(+), 27 deletions(-) diff --git a/packages/mui-material/src/Menu/Menu.d.ts b/packages/mui-material/src/Menu/Menu.d.ts index eaa0add5b9f2aa..55d390955ec613 100644 --- a/packages/mui-material/src/Menu/Menu.d.ts +++ b/packages/mui-material/src/Menu/Menu.d.ts @@ -2,13 +2,7 @@ import * as React from 'react'; import { SxProps } from '@mui/system'; import { InternalStandardProps as StandardProps } from '..'; import { PaperProps } from '../Paper'; -import { - PopoverProps, - PopoverSlots, - PopoverOwnerState, - PopoverBackdropSlotPropsOverrides, - PopoverTransitionSlotPropsOverrides, -} from '../Popover'; +import { PopoverProps } from '../Popover'; import { MenuListProps } from '../MenuList'; import { ModalProps } from '../Modal'; import { BackdropProps } from '../Backdrop'; @@ -27,7 +21,7 @@ export interface MenuListSlotPropsOverrides {} export interface MenuBackdropSlotPropsOverrides {} -export interface MenuSlots extends Pick { +export interface MenuSlots { /** * The component used for the popper. * @default Modal @@ -43,6 +37,16 @@ export interface MenuSlots extends Pick * @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< @@ -69,9 +73,9 @@ export type MenuSlotsAndSlotProps = CreateSlotsAndSlotProps< */ transition: SlotComponentProps< // use SlotComponentProps because transition slot does not support `component` and `sx` prop - React.ElementType, - PopoverTransitionSlotPropsOverrides, - PopoverOwnerState + React.ElementType, + TransitionProps & MenuTransitionSlotPropsOverrides, + MenuOwnerState >; /** * Props forwarded to the backdrop slot. @@ -79,8 +83,8 @@ export type MenuSlotsAndSlotProps = CreateSlotsAndSlotProps< */ backdrop: SlotProps< React.ElementType, - PopoverBackdropSlotPropsOverrides, - PopoverOwnerState + MenuBackdropSlotPropsOverrides, + MenuOwnerState >; } >; diff --git a/packages/mui-material/src/Menu/Menu.js b/packages/mui-material/src/Menu/Menu.js index c58fd6ff02173f..23f6df60f2a2a2 100644 --- a/packages/mui-material/src/Menu/Menu.js +++ b/packages/mui-material/src/Menu/Menu.js @@ -203,6 +203,11 @@ const Menu = React.forwardRef(function Menu(inProps, ref) { ownerState, }); + const resolvedTransitionProps = + typeof externalForwardedProps.slotProps.transition === 'function' + ? externalForwardedProps.slotProps.transition(ownerState) + : externalForwardedProps.slotProps.transition; + return ( { - const transitionProps = - typeof slotProps.transition === 'function' - ? slotProps.transition(innerState) - : slotProps.transition; - return { - ...transitionProps, - onEntering: (...args) => { - handleEntering(...args); - transitionProps?.onEntering?.(...args); - }, - }; + backdrop: + typeof slotProps.backdrop === 'function' + ? slotProps.backdrop(ownerState) + : slotProps.backdrop, + transition: { + ...resolvedTransitionProps, + onEntering: (...args) => { + handleEntering(...args); + resolvedTransitionProps?.onEntering?.(...args); + }, }, }} open={open} diff --git a/packages/mui-material/src/Menu/Menu.spec.tsx b/packages/mui-material/src/Menu/Menu.spec.tsx index 933c42822f18b1..c0f73c7fef2de6 100644 --- a/packages/mui-material/src/Menu/Menu.spec.tsx +++ b/packages/mui-material/src/Menu/Menu.spec.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import Menu from '@mui/material/Menu'; +import Menu, { MenuProps } from '@mui/material/Menu'; ; + +; + +function Custom(props: MenuProps) { + const { slotProps, ...dialogProps } = props; + return ( + { + const transitionProps = + typeof slotProps?.transition === 'function' + ? slotProps.transition(ownerState) + : slotProps?.transition; + return { + ...transitionProps, + onExited: (node) => { + transitionProps?.onExited?.(node); + }, + }; + }, + }} + {...dialogProps} + > + test + + ); +} diff --git a/packages/mui-material/src/Menu/Menu.test.js b/packages/mui-material/src/Menu/Menu.test.js index e8a735d551200c..b9e04e603aeaf2 100644 --- a/packages/mui-material/src/Menu/Menu.test.js +++ b/packages/mui-material/src/Menu/Menu.test.js @@ -10,10 +10,18 @@ import { } from '@mui/internal-test-utils'; import Menu, { menuClasses as classes } from '@mui/material/Menu'; import Popover from '@mui/material/Popover'; +import { modalClasses } from '@mui/material/Modal'; import { createTheme, ThemeProvider } from '@mui/material/styles'; import describeConformance from '../../test/describeConformance'; import { paperClasses } from '../Paper'; +const CustomTransition = React.forwardRef(function CustomTransition( + { in: inProp, appear, onEnter, onEntering, onExited, ownerState, ...props }, + ref, +) { + return
; +}); + describe('', () => { const { render } = createRenderer({ clock: 'fake' }); @@ -34,6 +42,17 @@ describe('', () => { expectedClassName: classes.list, testWithElement: null, // already tested with `testWithComponent` }, + backdrop: { + expectedClassName: modalClasses.backdrop, + testWithElement: React.forwardRef(({ invisible, ownerState, ...props }, ref) => ( + + )), + }, + transition: { + expectedClassName: null, + testWithComponent: CustomTransition, + testWithElement: CustomTransition, + }, }, testDeepOverrides: { slotName: 'list', slotClassName: classes.list }, testRootOverrides: { slotName: 'root', slotClassName: classes.root },