diff --git a/docs/data/material/components/material-icons/SearchIcons.js b/docs/data/material/components/material-icons/SearchIcons.js index faf1532ef9ad64..59321ebfafaf5b 100644 --- a/docs/data/material/components/material-icons/SearchIcons.js +++ b/docs/data/material/components/material-icons/SearchIcons.js @@ -292,8 +292,10 @@ const DialogDetails = React.memo(function DialogDetails(props) { setCopied1(false), + slotProps={{ + transition: { + onExited: () => setCopied1(false), + }, }} > @@ -304,7 +306,9 @@ const DialogDetails = React.memo(function DialogDetails(props) { <Tooltip placement="top" title={copied2 ? t('copied') : t('clickToCopy')} - TransitionProps={{ onExited: () => setCopied2(false) }} + slotProps={{ + transition: { onExited: () => setCopied2(false) }, + }} > <Markdown copyButtonHidden diff --git a/docs/data/material/components/tooltips/AnchorElTooltips.js b/docs/data/material/components/tooltips/AnchorElTooltips.js index 5de6a6adec73f4..f6ba12f5e8429b 100644 --- a/docs/data/material/components/tooltips/AnchorElTooltips.js +++ b/docs/data/material/components/tooltips/AnchorElTooltips.js @@ -23,16 +23,18 @@ export default function AnchorElTooltips() { title="Add" placement="top" arrow - PopperProps={{ - popperRef, - anchorEl: { - getBoundingClientRect: () => { - return new DOMRect( - positionRef.current.x, - areaRef.current.getBoundingClientRect().y, - 0, - 0, - ); + slotProps={{ + popper: { + popperRef, + anchorEl: { + getBoundingClientRect: () => { + return new DOMRect( + positionRef.current.x, + areaRef.current.getBoundingClientRect().y, + 0, + 0, + ); + }, }, }, }} diff --git a/docs/data/material/components/tooltips/AnchorElTooltips.tsx b/docs/data/material/components/tooltips/AnchorElTooltips.tsx index 48627973b82b9c..569f7ef37bab96 100644 --- a/docs/data/material/components/tooltips/AnchorElTooltips.tsx +++ b/docs/data/material/components/tooltips/AnchorElTooltips.tsx @@ -24,16 +24,18 @@ export default function AnchorElTooltips() { title="Add" placement="top" arrow - PopperProps={{ - popperRef, - anchorEl: { - getBoundingClientRect: () => { - return new DOMRect( - positionRef.current.x, - areaRef.current!.getBoundingClientRect().y, - 0, - 0, - ); + slotProps={{ + popper: { + popperRef, + anchorEl: { + getBoundingClientRect: () => { + return new DOMRect( + positionRef.current.x, + areaRef.current!.getBoundingClientRect().y, + 0, + 0, + ); + }, }, }, }} diff --git a/docs/data/material/components/tooltips/TransitionsTooltips.js b/docs/data/material/components/tooltips/TransitionsTooltips.js index f468119c6b1a0c..f2b08180781486 100644 --- a/docs/data/material/components/tooltips/TransitionsTooltips.js +++ b/docs/data/material/components/tooltips/TransitionsTooltips.js @@ -11,13 +11,22 @@ export default function TransitionsTooltips() { <Button>Grow</Button> </Tooltip> <Tooltip - TransitionComponent={Fade} - TransitionProps={{ timeout: 600 }} title="Add" + slots={{ + transition: Fade, + }} + slotProps={{ + transition: { timeout: 600 }, + }} > <Button>Fade</Button> </Tooltip> - <Tooltip TransitionComponent={Zoom} title="Add"> + <Tooltip + title="Add" + slots={{ + transition: Zoom, + }} + > <Button>Zoom</Button> </Tooltip> </div> diff --git a/docs/data/material/components/tooltips/TransitionsTooltips.tsx b/docs/data/material/components/tooltips/TransitionsTooltips.tsx index f468119c6b1a0c..f2b08180781486 100644 --- a/docs/data/material/components/tooltips/TransitionsTooltips.tsx +++ b/docs/data/material/components/tooltips/TransitionsTooltips.tsx @@ -11,13 +11,22 @@ export default function TransitionsTooltips() { <Button>Grow</Button> </Tooltip> <Tooltip - TransitionComponent={Fade} - TransitionProps={{ timeout: 600 }} title="Add" + slots={{ + transition: Fade, + }} + slotProps={{ + transition: { timeout: 600 }, + }} > <Button>Fade</Button> </Tooltip> - <Tooltip TransitionComponent={Zoom} title="Add"> + <Tooltip + title="Add" + slots={{ + transition: Zoom, + }} + > <Button>Zoom</Button> </Tooltip> </div> diff --git a/docs/data/material/components/tooltips/TransitionsTooltips.tsx.preview b/docs/data/material/components/tooltips/TransitionsTooltips.tsx.preview deleted file mode 100644 index 3a298ce9881fe9..00000000000000 --- a/docs/data/material/components/tooltips/TransitionsTooltips.tsx.preview +++ /dev/null @@ -1,13 +0,0 @@ -<Tooltip title="Add"> - <Button>Grow</Button> -</Tooltip> -<Tooltip - TransitionComponent={Fade} - TransitionProps={{ timeout: 600 }} - title="Add" -> - <Button>Fade</Button> -</Tooltip> -<Tooltip TransitionComponent={Zoom} title="Add"> - <Button>Zoom</Button> -</Tooltip> \ No newline at end of file diff --git a/docs/data/material/components/tooltips/TriggersTooltips.js b/docs/data/material/components/tooltips/TriggersTooltips.js index dce8b3610bce1f..ec111dda71a070 100644 --- a/docs/data/material/components/tooltips/TriggersTooltips.js +++ b/docs/data/material/components/tooltips/TriggersTooltips.js @@ -37,15 +37,17 @@ export default function TriggersTooltips() { <ClickAwayListener onClickAway={handleTooltipClose}> <div> <Tooltip - PopperProps={{ - disablePortal: true, - }} onClose={handleTooltipClose} open={open} disableFocusListener disableHoverListener disableTouchListener title="Add" + slotProps={{ + popper: { + disablePortal: true, + }, + }} > <Button onClick={handleTooltipOpen}>Click</Button> </Tooltip> diff --git a/docs/data/material/components/tooltips/TriggersTooltips.tsx b/docs/data/material/components/tooltips/TriggersTooltips.tsx index dce8b3610bce1f..ec111dda71a070 100644 --- a/docs/data/material/components/tooltips/TriggersTooltips.tsx +++ b/docs/data/material/components/tooltips/TriggersTooltips.tsx @@ -37,15 +37,17 @@ export default function TriggersTooltips() { <ClickAwayListener onClickAway={handleTooltipClose}> <div> <Tooltip - PopperProps={{ - disablePortal: true, - }} onClose={handleTooltipClose} open={open} disableFocusListener disableHoverListener disableTouchListener title="Add" + slotProps={{ + popper: { + disablePortal: true, + }, + }} > <Button onClick={handleTooltipOpen}>Click</Button> </Tooltip> 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 814f1a07349ab2..390c5f6e284808 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 @@ -1472,6 +1472,36 @@ The Tooltip's prop `componentsProps` was deprecated in favor of `slotProps`: /> ``` +### \*Component props + +All of the Tooltip's slot (`*Component`) props were deprecated in favor of equivalent `slots` entries: + +```diff + <Tooltip +- PopperComponent={CustomPopperComponent} +- TransitionComponent={CustomTransitionComponent} ++ slots={{ ++ popper: CustomPopperComponent, ++ transition: CustomTransitionComponent, ++ }} + /> +``` + +### \*Props props + +All of the Tooltip's slot props (`*Props`) props were deprecated in favor of equivalent `slotProps` entries: + +```diff + <Tooltip +- PopperProps={CustomPopperProps} +- TransitionProps={CustomTransitionProps} ++ slotProps={{ ++ popper: CustomPopperProps, ++ transition: CustomTransitionProps, ++ }} + /> +``` + ## StepLabel Use the [codemod](https://github.com/mui/material-ui/tree/HEAD/packages/mui-codemod#step-label-props) below to migrate the code as described in the following sections: diff --git a/docs/pages/material-ui/api/tooltip.json b/docs/pages/material-ui/api/tooltip.json index da38990cf9ce1d..3a0d7ca9d80230 100644 --- a/docs/pages/material-ui/api/tooltip.json +++ b/docs/pages/material-ui/api/tooltip.json @@ -55,8 +55,16 @@ }, "default": "'bottom'" }, - "PopperComponent": { "type": { "name": "elementType" }, "default": "Popper" }, - "PopperProps": { "type": { "name": "object" }, "default": "{}" }, + "PopperComponent": { + "type": { "name": "elementType" }, + "deprecated": true, + "deprecationInfo": "Use <code>slots.popper</code> instead. This prop will be removed in v7. <a href=\"/material-ui/migration/migrating-from-deprecated-apis/\">How to migrate</a>." + }, + "PopperProps": { + "type": { "name": "object" }, + "deprecated": true, + "deprecationInfo": "Use <code>slotProps.popper</code> instead. This prop will be removed in v7. <a href=\"/material-ui/migration/migrating-from-deprecated-apis/\">How to migrate</a>." + }, "slotProps": { "type": { "name": "shape", @@ -79,8 +87,16 @@ "additionalInfo": { "sx": true } }, "title": { "type": { "name": "node" } }, - "TransitionComponent": { "type": { "name": "elementType" }, "default": "Grow" }, - "TransitionProps": { "type": { "name": "object" } } + "TransitionComponent": { + "type": { "name": "elementType" }, + "deprecated": true, + "deprecationInfo": "Use <code>slots.transition</code> instead. This prop will be removed in v7. <a href=\"/material-ui/migration/migrating-from-deprecated-apis/\">How to migrate</a>." + }, + "TransitionProps": { + "type": { "name": "object" }, + "deprecated": true, + "deprecationInfo": "Use <code>slotProps.transition</code> instead. This prop will be removed in v7. <a href=\"/material-ui/migration/migrating-from-deprecated-apis/\">How to migrate</a>." + } }, "name": "Tooltip", "imports": [ diff --git a/packages/mui-codemod/README.md b/packages/mui-codemod/README.md index f71396dcf265fe..92dd54c9da5749 100644 --- a/packages/mui-codemod/README.md +++ b/packages/mui-codemod/README.md @@ -1312,6 +1312,43 @@ npx @mui/codemod@next deprecations/outlined-input-props <path> npx @mui/codemod@next deprecations/slider-props <path> ``` +#### `step-connector-classes` + +JS transforms: + +```diff + import { stepConnectorClasses } from '@mui/material/StepConnector'; + + MuiStepConnector: { + styleOverrides: { + root: { +- [`& .${stepConnectorClasses.lineHorizontal}`]: { ++ [`&.${stepConnectorClasses.horizontal} > .${stepConnectorClasses.line}`]: { + color: 'red', + }, +- [`& .${stepConnectorClasses.lineVertical}`]: { ++ [`&.${stepConnectorClasses.vertical} > .${stepConnectorClasses.line}`]: { + color: 'red', + }, + }, + }, + }, +``` + +CSS transforms: + +```diff +-.MuiToggleButtonGroup-root .MuiToggleButtonGroup-groupedHorizontal ++.MuiToggleButtonGroup-root.MuiToggleButtonGroup-horizontal > .MuiToggleButtonGroup-grouped +-.MuiToggleButtonGroup-root .MuiToggleButtonGroup-groupedVertical ++.MuiToggleButtonGroup-root.MuiToggleButtonGroup-vertical > .MuiToggleButtonGroup-grouped + /> +``` + +```bash +npx @mui/codemod@latest deprecations/toggle-button-group-classes <path> +``` + #### `tooltip-props` ```diff @@ -1334,33 +1371,46 @@ npx @mui/codemod@next deprecations/slider-props <path> }, ``` -```bash -npx @mui/codemod@next deprecations/tooltip-props <path> +```diff + <Tooltip +- PopperComponent={CustomPopperComponent} +- TransitionComponent={CustomTransitionComponent} +- PopperProps={CustomPopperProps} +- TransitionProps={CustomTransitionProps} ++ slots={{ ++ popper: CustomPopperComponent, ++ transition: CustomTransitionComponent, ++ }} ++ slotProps={{ ++ popper: CustomPopperProps, ++ transition: CustomTransitionProps, ++ }} + /> ``` -#### `step-connector-classes` - -JS transforms: - ```diff - import { stepConnectorClasses } from '@mui/material/StepConnector'; - - MuiStepConnector: { - styleOverrides: { - root: { -- [`& .${stepConnectorClasses.lineHorizontal}`]: { -+ [`&.${stepConnectorClasses.horizontal} > .${stepConnectorClasses.line}`]: { - color: 'red', - }, -- [`& .${stepConnectorClasses.lineVertical}`]: { -+ [`&.${stepConnectorClasses.vertical} > .${stepConnectorClasses.line}`]: { - color: 'red', - }, - }, + MuiTooltip: { + defaultProps: { +- PopperComponent: CustomPopperComponent, +- TransitionComponent: CustomTransitionComponent, +- PopperProps: CustomPopperProps, +- TransitionProps: CustomTransitionProps, ++ slots: { ++ popper: CustomPopperComponent, ++ transition: CustomTransitionComponent, ++ }, ++ slotProps: { ++ popper: CustomPopperProps, ++ transition: CustomTransitionProps, ++ }, }, }, ``` +```bash +npx @mui/codemod@next deprecations/tooltip-props <path> +``` + #### `step-label-props` ```diff diff --git a/packages/mui-codemod/src/deprecations/all/deprecations-all.js b/packages/mui-codemod/src/deprecations/all/deprecations-all.js index bd443107e446eb..52c2b881e8af47 100644 --- a/packages/mui-codemod/src/deprecations/all/deprecations-all.js +++ b/packages/mui-codemod/src/deprecations/all/deprecations-all.js @@ -22,6 +22,7 @@ import transformStepConnectorClasses from '../step-connector-classes'; import transformStepLabelProps from '../step-label-props'; import transformTextFieldProps from '../text-field-props'; import transformToggleButtonGroupClasses from '../toggle-button-group-classes'; +import transformTooltipProps from '../tooltip-props'; /** * @param {import('jscodeshift').FileInfo} file @@ -52,6 +53,7 @@ export default function deprecationsAll(file, api, options) { file.source = transformStepLabelProps(file, api, options); file.source = transformTextFieldProps(file, api, options); file.source = transformToggleButtonGroupClasses(file, api, options); + file.source = transformTooltipProps(file, api, options); return file.source; } diff --git a/packages/mui-codemod/src/deprecations/tooltip-props/test-cases/actual.js b/packages/mui-codemod/src/deprecations/tooltip-props/test-cases/actual.js index a02495c65013ca..34c6c5712d0b6a 100644 --- a/packages/mui-codemod/src/deprecations/tooltip-props/test-cases/actual.js +++ b/packages/mui-codemod/src/deprecations/tooltip-props/test-cases/actual.js @@ -1,4 +1,5 @@ import Tooltip from '@mui/material/Tooltip'; +import {Tooltip as MyTooltip} from '@mui/material'; <Tooltip components={{ @@ -58,3 +59,37 @@ import Tooltip from '@mui/material/Tooltip'; transition: componentsTransitionProps }} />; + +<Tooltip + PopperComponent={CustomPopper} + TransitionComponent={CustomTransition} + PopperProps={{ disablePortal: true }} + TransitionProps={{ timeout: 200 }} +/>; + +<Tooltip + PopperComponent={CustomPopper} + TransitionComponent={CustomTransition} + PopperProps={{ disablePortal: true }} + TransitionProps={{ timeout: 200 }} + slotProps={{ + tooltip: { height: 20 } + }} + slots={{ + tooltip: "div", + }} +/>; + +<MyTooltip + PopperComponent={CustomPopper} + TransitionComponent={CustomTransition} + PopperProps={{ disablePortal: true }} + TransitionProps={{ timeout: 200 }} +/>; + +<CustomTooltip + PopperComponent={CustomPopper} + TransitionComponent={CustomTransition} + PopperProps={{ disablePortal: true }} + TransitionProps={{ timeout: 200 }} +/> diff --git a/packages/mui-codemod/src/deprecations/tooltip-props/test-cases/expected.js b/packages/mui-codemod/src/deprecations/tooltip-props/test-cases/expected.js index a6e62ef6c7d73f..62b6b005ac1386 100644 --- a/packages/mui-codemod/src/deprecations/tooltip-props/test-cases/expected.js +++ b/packages/mui-codemod/src/deprecations/tooltip-props/test-cases/expected.js @@ -1,4 +1,5 @@ import Tooltip from '@mui/material/Tooltip'; +import {Tooltip as MyTooltip} from '@mui/material'; <Tooltip slots={{ @@ -63,3 +64,42 @@ import Tooltip from '@mui/material/Tooltip'; ...slotsTransitionProps } }} />; + +<Tooltip + slots={{ + popper: CustomPopper, + transition: CustomTransition + }} + slotProps={{ + popper: { disablePortal: true }, + transition: { timeout: 200 } + }} />; + +<Tooltip + slotProps={{ + tooltip: { height: 20 }, + popper: { disablePortal: true }, + transition: { timeout: 200 } + }} + slots={{ + tooltip: "div", + popper: CustomPopper, + transition: CustomTransition + }} />; + +<MyTooltip + slots={{ + popper: CustomPopper, + transition: CustomTransition + }} + slotProps={{ + popper: { disablePortal: true }, + transition: { timeout: 200 } + }} />; + +<CustomTooltip + PopperComponent={CustomPopper} + TransitionComponent={CustomTransition} + PopperProps={{ disablePortal: true }} + TransitionProps={{ timeout: 200 }} +/> diff --git a/packages/mui-codemod/src/deprecations/tooltip-props/test-cases/theme.actual.js b/packages/mui-codemod/src/deprecations/tooltip-props/test-cases/theme.actual.js index d6933e8bc29102..6fd591c423774d 100644 --- a/packages/mui-codemod/src/deprecations/tooltip-props/test-cases/theme.actual.js +++ b/packages/mui-codemod/src/deprecations/tooltip-props/test-cases/theme.actual.js @@ -39,3 +39,30 @@ fn({ }, }, }); +fn({ + MuiTooltip: { + defaultProps: { + PopperComponent: CustomPopper, + TransitionComponent: CustomTransition, + PopperProps: { disablePortal: true }, + TransitionProps: { timeout: 200 }, + }, + }, +}); + +fn({ + MuiTooltip: { + defaultProps: { + PopperComponent: CustomPopper, + TransitionComponent: CustomTransition, + PopperProps: { disablePortal: true }, + TransitionProps: { timeout: 200 }, + slotProps: { + tooltip: { height: 20 } + }, + slots: { + tooltip: "div", + }, + }, + }, +}); diff --git a/packages/mui-codemod/src/deprecations/tooltip-props/test-cases/theme.expected.js b/packages/mui-codemod/src/deprecations/tooltip-props/test-cases/theme.expected.js index ad6b795e2c4d53..8d077ba5aa033d 100644 --- a/packages/mui-codemod/src/deprecations/tooltip-props/test-cases/theme.expected.js +++ b/packages/mui-codemod/src/deprecations/tooltip-props/test-cases/theme.expected.js @@ -70,3 +70,36 @@ fn({ }, }, }); +fn({ + MuiTooltip: { + defaultProps: { + slots: { + popper: CustomPopper, + transition: CustomTransition + }, + + slotProps: { + popper: { disablePortal: true }, + transition: { timeout: 200 } + } + }, + }, +}); + +fn({ + MuiTooltip: { + defaultProps: { + slotProps: { + tooltip: { height: 20 }, + popper: { disablePortal: true }, + transition: { timeout: 200 } + }, + + slots: { + tooltip: "div", + popper: CustomPopper, + transition: CustomTransition + } + }, + }, +}); diff --git a/packages/mui-codemod/src/deprecations/tooltip-props/tooltip-props.js b/packages/mui-codemod/src/deprecations/tooltip-props/tooltip-props.js index feb7e35348d69b..fc9af0dcd84939 100644 --- a/packages/mui-codemod/src/deprecations/tooltip-props/tooltip-props.js +++ b/packages/mui-codemod/src/deprecations/tooltip-props/tooltip-props.js @@ -1,4 +1,6 @@ import replaceComponentsWithSlots from '../utils/replaceComponentsWithSlots'; +import movePropIntoSlots from '../utils/movePropIntoSlots'; +import movePropIntoSlotProps from '../utils/movePropIntoSlotProps'; /** * @param {import('jscodeshift').FileInfo} file @@ -11,5 +13,33 @@ export default function transformer(file, api, options) { replaceComponentsWithSlots(j, { root, componentName: 'Tooltip' }); + movePropIntoSlots(j, { + root, + componentName: 'Tooltip', + propName: 'PopperComponent', + slotName: 'popper', + }); + + movePropIntoSlotProps(j, { + root, + componentName: 'Tooltip', + propName: 'PopperProps', + slotName: 'popper', + }); + + movePropIntoSlots(j, { + root, + componentName: 'Tooltip', + propName: 'TransitionComponent', + slotName: 'transition', + }); + + movePropIntoSlotProps(j, { + root, + componentName: 'Tooltip', + propName: 'TransitionProps', + slotName: 'transition', + }); + return root.toSource(printOptions); } diff --git a/packages/mui-material/src/Tooltip/Tooltip.d.ts b/packages/mui-material/src/Tooltip/Tooltip.d.ts index 9991be721dcccc..cfe385f8df0d19 100644 --- a/packages/mui-material/src/Tooltip/Tooltip.d.ts +++ b/packages/mui-material/src/Tooltip/Tooltip.d.ts @@ -151,12 +151,12 @@ export interface TooltipProps extends StandardProps<React.HTMLAttributes<HTMLDiv | 'top'; /** * The component used for the popper. - * @default Popper + * @deprecated Use `slots.popper` instead. This prop will be removed in v7. [How to migrate](/material-ui/migration/migrating-from-deprecated-apis/). */ PopperComponent?: React.JSXElementConstructor<PopperProps>; /** * Props applied to the [`Popper`](/material-ui/api/popper/) element. - * @default {} + * @deprecated Use `slotProps.popper` instead. This prop will be removed in v7. [How to migrate](/material-ui/migration/migrating-from-deprecated-apis/). */ PopperProps?: Partial<PopperProps>; /** @@ -201,7 +201,7 @@ export interface TooltipProps extends StandardProps<React.HTMLAttributes<HTMLDiv /** * The component used for the transition. * [Follow this guide](/material-ui/transitions/#transitioncomponent-prop) to learn more about the requirements for this component. - * @default Grow + * @deprecated Use `slots.transition` instead. This prop will be removed in v7. [How to migrate](/material-ui/migration/migrating-from-deprecated-apis/). */ TransitionComponent?: React.JSXElementConstructor< TransitionProps & { children: React.ReactElement<any, any> } @@ -209,6 +209,7 @@ export interface TooltipProps extends StandardProps<React.HTMLAttributes<HTMLDiv /** * 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 `slotProps.transition` instead. This prop will be removed in v7. [How to migrate](/material-ui/migration/migrating-from-deprecated-apis/). */ TransitionProps?: TransitionProps; } diff --git a/packages/mui-material/src/Tooltip/Tooltip.js b/packages/mui-material/src/Tooltip/Tooltip.js index a3115d00e0620d..93ce567bfde846 100644 --- a/packages/mui-material/src/Tooltip/Tooltip.js +++ b/packages/mui-material/src/Tooltip/Tooltip.js @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'; import clsx from 'clsx'; import useTimeout, { Timeout } from '@mui/utils/useTimeout'; import elementAcceptingRef from '@mui/utils/elementAcceptingRef'; -import { appendOwnerState } from '@mui/base/utils'; +import { appendOwnerState, resolveComponentProps } from '@mui/base/utils'; import composeClasses from '@mui/utils/composeClasses'; import { alpha } from '@mui/system/colorManipulator'; import { useRtl } from '@mui/system/RtlProvider'; @@ -19,6 +19,7 @@ import useId from '../utils/useId'; import useIsFocusVisible from '../utils/useIsFocusVisible'; import useControlled from '../utils/useControlled'; import tooltipClasses, { getTooltipUtilityClass } from './tooltipClasses'; +import useSlot from '../utils/useSlot'; const useThemeProps = createUseThemeProps('MuiTooltip'); @@ -330,11 +331,11 @@ const Tooltip = React.forwardRef(function Tooltip(inProps, ref) { open: openProp, placement = 'bottom', PopperComponent: PopperComponentProp, - PopperProps = {}, + PopperProps, slotProps = {}, slots = {}, title, - TransitionComponent: TransitionComponentProp = Grow, + TransitionComponent: TransitionComponentProp, TransitionProps, ...other } = props; @@ -654,6 +655,19 @@ const Tooltip = React.forwardRef(function Tooltip(inProps, ref) { } } + const ownerState = React.useMemo( + () => ({ + ...props, + isRtl, + arrow, + disableInteractive, + placement, + PopperComponentProp, + touch: ignoreNonTouchEvents.current, + }), + [PopperComponentProp, arrow, disableInteractive, isRtl, placement, props], + ); + const popperOptions = React.useMemo(() => { let tooltipModifiers = [ { @@ -666,53 +680,76 @@ const Tooltip = React.forwardRef(function Tooltip(inProps, ref) { }, ]; - if (PopperProps.popperOptions?.modifiers) { - tooltipModifiers = tooltipModifiers.concat(PopperProps.popperOptions.modifiers); + const resolvedSlotProps = resolveComponentProps(slotProps.popper, ownerState); + if (resolvedSlotProps?.popperOptions?.modifiers || PopperProps?.popperOptions?.modifiers) { + tooltipModifiers = tooltipModifiers.concat( + resolvedSlotProps?.popperOptions?.modifiers ?? PopperProps?.popperOptions.modifiers, + ); } return { - ...PopperProps.popperOptions, + ...(resolvedSlotProps?.popperProps ?? PopperProps?.popperOptions), modifiers: tooltipModifiers, }; - }, [arrowRef, PopperProps]); - - const ownerState = { - ...props, - isRtl, - arrow, - disableInteractive, - placement, - PopperComponentProp, - touch: ignoreNonTouchEvents.current, - }; + }, [arrowRef, PopperProps, slotProps, ownerState]); const classes = useUtilityClasses(ownerState); - const PopperComponent = slots.popper ?? components.Popper ?? TooltipPopper; - const TransitionComponent = - slots.transition ?? components.Transition ?? TransitionComponentProp ?? Grow; - const TooltipComponent = slots.tooltip ?? components.Tooltip ?? TooltipTooltip; - const ArrowComponent = slots.arrow ?? components.Arrow ?? TooltipArrow; + const externalForwardedProps = { + slots: { + popper: components.Popper ?? PopperComponentProp, + transition: components.Transition ?? TransitionComponentProp, + tooltip: components.Tooltip, + arrow: components.Arrow, + ...slots, + }, + slotProps: { + popper: PopperProps, + transition: TransitionProps, + ...componentsProps, + ...slotProps, + }, + }; - const popperProps = appendOwnerState( - PopperComponent, - { - ...PopperProps, - ...(slotProps.popper ?? componentsProps.popper), - className: clsx( - classes.popper, - PopperProps?.className, - (slotProps.popper ?? componentsProps.popper)?.className, - ), + const [SlotPopper, popperProps] = useSlot('popper', { + elementType: TooltipPopper, + externalForwardedProps, + ownerState, + className: [classes.popper, PopperProps?.className], + additionalProps: { + as: PopperComponentProp ?? Popper, + placement, + anchorEl: followCursor + ? { + getBoundingClientRect: () => ({ + top: cursorPosition.y, + left: cursorPosition.x, + right: cursorPosition.x, + bottom: cursorPosition.y, + width: 0, + height: 0, + }), + } + : childNode, + popperRef, + open: childNode ? open : false, + id, + transition: true, + ...interactiveWrapperListeners, + popperOptions, }, + }); + const [SlotTransition, transitionProps] = useSlot('transition', { + elementType: Grow, + externalForwardedProps, ownerState, - ); + additionalProps: { + timeout: theme.transitions.duration.shorter, + }, + }); - const transitionProps = appendOwnerState( - TransitionComponent, - { ...TransitionProps, ...(slotProps.transition ?? componentsProps.transition) }, - ownerState, - ); + const TooltipComponent = slots.tooltip ?? components.Tooltip ?? TooltipTooltip; + const ArrowComponent = slots.arrow ?? components.Arrow ?? TooltipArrow; const tooltipProps = appendOwnerState( TooltipComponent, @@ -735,44 +772,16 @@ const Tooltip = React.forwardRef(function Tooltip(inProps, ref) { return ( <React.Fragment> {React.cloneElement(children, childrenProps)} - <PopperComponent - as={PopperComponentProp ?? Popper} - placement={placement} - anchorEl={ - followCursor - ? { - getBoundingClientRect: () => ({ - top: cursorPosition.y, - left: cursorPosition.x, - right: cursorPosition.x, - bottom: cursorPosition.y, - width: 0, - height: 0, - }), - } - : childNode - } - popperRef={popperRef} - open={childNode ? open : false} - id={id} - transition - {...interactiveWrapperListeners} - {...popperProps} - popperOptions={popperOptions} - > + <SlotPopper {...popperProps}> {({ TransitionProps: TransitionPropsInner }) => ( - <TransitionComponent - timeout={theme.transitions.duration.shorter} - {...TransitionPropsInner} - {...transitionProps} - > + <SlotTransition {...TransitionPropsInner} {...transitionProps}> <TooltipComponent {...tooltipProps}> {title} {arrow ? <ArrowComponent {...tooltipArrowProps} ref={setArrowRef} /> : null} </TooltipComponent> - </TransitionComponent> + </SlotTransition> )} - </PopperComponent> + </SlotPopper> </React.Fragment> ); }); @@ -926,12 +935,12 @@ Tooltip.propTypes /* remove-proptypes */ = { ]), /** * The component used for the popper. - * @default Popper + * @deprecated Use `slots.popper` instead. This prop will be removed in v7. [How to migrate](/material-ui/migration/migrating-from-deprecated-apis/). */ PopperComponent: PropTypes.elementType, /** * Props applied to the [`Popper`](/material-ui/api/popper/) element. - * @default {} + * @deprecated Use `slotProps.popper` instead. This prop will be removed in v7. [How to migrate](/material-ui/migration/migrating-from-deprecated-apis/). */ PopperProps: PropTypes.object, /** @@ -976,12 +985,13 @@ Tooltip.propTypes /* remove-proptypes */ = { /** * The component used for the transition. * [Follow this guide](/material-ui/transitions/#transitioncomponent-prop) to learn more about the requirements for this component. - * @default Grow + * @deprecated Use `slots.transition` instead. This prop will be removed in v7. [How to migrate](/material-ui/migration/migrating-from-deprecated-apis/). */ TransitionComponent: PropTypes.elementType, /** * 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 `slotProps.transition` instead. This prop will be removed in v7. [How to migrate](/material-ui/migration/migrating-from-deprecated-apis/). */ TransitionProps: PropTypes.object, };